diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index d20fe7f60048..91e9458e9a3d 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "microsoft.dotnet.darc": { - "version": "1.1.0-beta.25064.2", + "version": "1.1.0-beta.25081.2", "commands": [ "darc" ] diff --git a/.gitattributes b/.gitattributes index 395c74ff4cd5..2f46e347155a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -10,6 +10,12 @@ ############################################################################### *.xlf linguist-generated=true +############################################################################### +# Set default behavior to: +# don't collapse these files in PRs +############################################################################### +**/build/** linguist-generated=false + ############################################################################### # Set file behavior to: # treat as text diff --git a/.vsts-ci.yml b/.vsts-ci.yml index d5f5f34e84b9..6315d97a9945 100644 --- a/.vsts-ci.yml +++ b/.vsts-ci.yml @@ -5,7 +5,7 @@ trigger: branches: include: - main - - release/9.0.2xx + - release/9.0.3xx - internal/release/* - exp/* @@ -22,6 +22,10 @@ parameters: displayName: Run A Test Build type: boolean default: false +- name: enableArm64Job + displayName: Enables the ARM64 job + type: boolean + default: false variables: - template: /eng/pipelines/templates/variables/sdk-defaults.yml @@ -297,7 +301,7 @@ extends: officialBuildProperties: $(_officialBuildProperties) runTests: false ### ARM64 TESTBUILD ### - - ${{ if or(eq(parameters.runTestBuild, true), eq(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if and(or(eq(parameters.runTestBuild, true), eq(variables['Build.Reason'], 'PullRequest')), eq(parameters.enableArm64Job, true)) }}: - template: /eng/pipelines/templates/jobs/sdk-job-matrix.yml@self parameters: pool: diff --git a/.vsts-pr.yml b/.vsts-pr.yml index 68b652751d4d..2e5c086a70e4 100644 --- a/.vsts-pr.yml +++ b/.vsts-pr.yml @@ -14,6 +14,12 @@ pr: - README.md - CODEOWNERS +parameters: +- name: enableArm64Job + displayName: Enables the ARM64 job + type: boolean + default: false + variables: - template: /eng/pipelines/templates/variables/sdk-defaults.yml # Variables used: DncEngPublicBuildPool @@ -64,17 +70,18 @@ stages: os: macOS helixTargetQueue: osx.13.amd64.open ### ARM64 ### - - template: /eng/pipelines/templates/jobs/sdk-job-matrix.yml - parameters: - pool: - name: Azure Pipelines - vmImage: macOS-latest - os: macOS - helixTargetQueue: osx.13.arm64.open - macOSJobParameterSets: - - categoryName: TestBuild - buildArchitecture: arm64 - runtimeIdentifier: osx-arm64 + - ${{ if eq(parameters.enableArm64Job, true) }}: + - template: /eng/pipelines/templates/jobs/sdk-job-matrix.yml + parameters: + pool: + name: Azure Pipelines + vmImage: macOS-latest + os: macOS + helixTargetQueue: osx.13.arm64.open + macOSJobParameterSets: + - categoryName: TestBuild + buildArchitecture: arm64 + runtimeIdentifier: osx-arm64 ############### DOTNET-FORMAT ############### - template: /eng/dotnet-format/dotnet-format-integration.yml diff --git a/Directory.Packages.props b/Directory.Packages.props index 2e3b4ae1f740..d05494c58666 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -94,7 +94,6 @@ - diff --git a/documentation/general/ExecutingCustomerCode.md b/documentation/general/ExecutingCustomerCode.md new file mode 100644 index 000000000000..e087065a5822 --- /dev/null +++ b/documentation/general/ExecutingCustomerCode.md @@ -0,0 +1,78 @@ +# Executing Customer Code + +## Summary + +When customers discover issues with the .NET SDK, we often need more information to see how exactly their scenarios differ from the (presumably working) mainline scenarios. This additional information often takes the form of a 'repro' or set of steps by which we can see the error ourselves and walk through what is happening as their scenario plays out and how it ultimately diverged from our expectations. + +Blindly executing, or even just opening in an IDE like Visual Studio without intending to build, unvetted customer code can be a security hazard, however, not just for the machine executing the code but for any machine on the same network and any service accessible using credentials they can access through those machines. In this way, a malicious actor can exfiltrate sensitive Microsoft data, including information about other Microsoft employees, proprietary code, or private customer data. They may even be able to take down a service or introduce further security bugs in shipping products. Indeed, the most common vector hackers use to gain access is through compromising one or more individual users with employee credentials. At Microsoft where security is paramount, we want to prevent such hacks. + +This document contains recommended best practices on how to securely test users' code. They are arranged in order of security with the most secure at the top. This should also be the priority you should use to stay secure when executing code. + +## Strategies for Staying Secure + +### Binary Logs + +MSBuild binary logs (binlogs) are structured data covering what happened during a build. Many operations that aren't obviously 'builds' such as publish (`dotnet publish`) or pack (`dotnet pack`) include building as part or all of the process, which makes them very useful for learning more about and potentially diagnosing a variety of potential problems. Furthermore, they are safe in the sense that analyzing a binlog does not expose your system to risks. + +To provide information to customers about collecting binlogs, direct them to: +https://aka.ms/msbuild/binlog + +It is important to note, however, that binlogs often collect secrets as part of the information relevant to the build. A binlog of a simplified repro can work as well, but it may be difficult to create a simple repro. Customers are sometimes concerned (with good reason) about sharing binlogs of their real (or simplified) builds. If so, they can attempt to redact secrets from their binlog, either via the [MSBuild Structured Log Viewer](https://msbuildlog.com/#redaction) or with [binlogtool](https://www.nuget.org/packages/binlogtool). If that isn't sufficient, or if the reported issue does not involve MSBuild, another option may be more relevant. + +### Windows Sandbox + +Windows Sandbox permits safely running any operation in a controlled, isolated environment where it will not affect your machine or Microsoft in any detrimental way. More information can be found [here](https://learn.microsoft.com/windows/security/application-security/application-isolation/windows-sandbox/windows-sandbox-overview). If the steps a customer provides for reproducing their scenario can be executed in Windows Sandbox, it is the safest place to do so. Unfortunately, Sandbox does come with a few notable downsides: +1. Windows Sandbox only exists for Windows. If a customer's scenario only reproduces on macOS or linux, it will not be able to be reproduced on Windows, and Sandbox is not helpful. +2. When Sandbox exits for any reason, all data is lost. This means, for instance, that if the computer hosting Sandbox restarts while Sandbox is open, any progress you might have made in putting together the customer's repro scenario is lost. +3. Sandbox is essentially empty when you first create it. It has internet access as long as your host computer has internet access, but it will be missing various programs and tools you may need to reproduce the customer's problem. Such programs and tools need to be downloaded anew every time you want to use Sandbox. + +Conveniently, however, it is relatively easy to copy files from your host computer into Sandbox, and as noted earlier, it is a secure, isolated environment, so it is an excellent choice if it is viable. + +Before executing customer code in Windows Sandbox, make sure to [disable networking](https://learn.microsoft.com/windows/security/application-security/application-isolation/windows-sandbox/windows-sandbox-configure-using-wsb-file#networking). + +### Create Your Own Solution + +Depending on how well you understand the customer's scenario, you may or may not understand ahead of time the most likely problem, but if it's possible to create your own solution that reproduces the issue the customer alluded to in their report, and you understand all the steps it took to create that solution, that is a safe method for obtaining a project to test and debug. Note that this is only a secure method if you understand all steps involved in creating the test project. "Copy project file provided by customer to disk and build it" does not count as a well-understood pair of steps. + +### Create a Virtual Machine Without Your Credentials + +Creating and using a virtual machine (VM) without your credentials is another secure way to test a customer's code, as it's disconnected from either your credentials or your computer. It is important if using this method to ensure that you do not give your VM your credentials at any point such as, for example, signing into your Microsoft account so you can use Visual Studio Enterprise. + +The other disadvantage of this approach is that it can take a lot of time to select appropriate parameters for your VM, start it, connect to it, set it up properly for your scenario, and execute the scenario. Unlike Sandbox, it can retain certain information across restarts, but it may lose active work just as your computer loses active work when you restart it. It's important to keep in mind that many VMs restart automatically at a fixed time every day when not in use to save resources. + +That said, this is a secure means for executing a customer's scenario, and it works for any operating system and can even be configured to work for other architectures. Note that using a VM in the cloud costs real money, though a local VM (such as using [Hyper-V](https://learn.microsoft.com/windows-server/virtualization/hyper-v/get-started/create-a-virtual-machine-in-hyper-v)) typically does not. + +For Microsoft employees, [DevTestLab](https://ms.portal.azure.com/#browse/Microsoft.Compute%2FVirtualMachines) can help you create VMs. + +### Read Code + +If none of the above methods work, it may be viable to read all customer code carefully to ensure that no part of it is risky or malicious. Many IDEs such as Visual Studio automatically run design-time builds when code is open. As a result, even just opening a malicious code base in Visual Studio can lead to exploits. Prefer an IDE that does not run design-time builds. Some examples include: +1. Visual Studio Code (if no addons are installed) +2. Notepad +3. Emacs/Vim + +Some examples of specific patterns to watch out for that can cause issues include: +1. PackageReferences. These download code from the internet and permit its execution locally. If you are unfamiliar with any package in a PackageReference, this is insecure. +2. MSBuild SDKs. At the top of many .NET projects is a line that includes `Sdk=""`. This automatically imports build logic associated with the specified SDK. If you are unfamiliar with the specified SDK, ensure it is secure before building any code including it. +3. MSBuild tasks. Within a `Target` block are MSBuild Tasks. Many of these, including `Exec` and `DownloadFile` execute logic that pulls code or build logic from the internet and may execute it. If you are unfamiliar with any MSBuild Task in a customer-provided project, ensure you fully understand its semantics before executing it (by building). +4. Typos. NuGet packages starting with Microsoft. and System. can only be pushed to nuget.org by Microsoft accounts, but Mircosoft and Sysstem are unregulated. +5. Malicious NuGet.Config files. Even if a PackageReference points to a package you're familiar with, perhaps even a Microsoft. or System. package, a NuGet.Config file can dictate searching in a different package source first that may not be secure and may include a malicious version of the package. + +More examples of patterns that can easily be exploited by malicious users can be found [here](https://aka.ms/msbuild-security-documentation) + +In addition to those more specific examples, it is important to follow the principle of least privilege. This means, for instance, that when on linux, you should only run a command as root if that's truly necessary to reproduce the customer's scenario. On Windows, you should only use an admin terminal if it's necessary. + +## Response to Malicious Repros + +If you discover that a customer provided a malicious project or solution, there are several steps. You should do all of these if possible. + +1. Most importantly, do not keep any vestige of the repro on your machine. Do not follow their steps. +2. Add a note to the issue that it was malicious. Include this information in the title if possible. +3. Delete the contents of the repro steps. (On GitHub, it can still be found by looking at your edit.) +4. Report the infraction using https://aka.ms/reportitnow (This step is only available to Microsoft employees.) +5. Report your finding to your manager and your security team. +6. Depending on the severity of the issue, consider banning the user from GitHub. + +If you are external, you may not be able to follow all of these steps. Reach out to someone from our team to help facilitate doing all these. + +Last but not least, thank you for helping keep Microsoft secure! \ No newline at end of file diff --git a/documentation/package-table.md b/documentation/package-table.md index cb7f1380d4d3..ab64a6cacf7a 100644 --- a/documentation/package-table.md +++ b/documentation/package-table.md @@ -1,20 +1,20 @@ ### Table -------------------------------------------------------------------------------------- -| Platform | main
(10.0.x Runtime) | 9.0.2xx
(9.0 Runtime) | 9.0.1xx
(9.0 Runtime) | +| Platform | main
(10.0.x Runtime) | 9.0.3xx
(9.0.x Runtime) | 9.0.2xx
(9.0.x Runtime) | | :--------- | :----------: | :----------: | :----------: | -| **Windows x64** | [![][win-x64-badge-main]][win-x64-version-main]
[Installer][win-x64-installer-main] - [Checksum][win-x64-installer-checksum-main]
[zip][win-x64-zip-main] - [Checksum][win-x64-zip-checksum-main] | [![][win-x64-badge-9.0.2XX]][win-x64-version-9.0.2XX]
[Installer][win-x64-installer-9.0.2XX] - [Checksum][win-x64-installer-checksum-9.0.2XX]
[zip][win-x64-zip-9.0.2XX] - [Checksum][win-x64-zip-checksum-9.0.2XX] | [![][win-x64-badge-9.0.1XX]][win-x64-version-9.0.1XX]
[Installer][win-x64-installer-9.0.1XX] - [Checksum][win-x64-installer-checksum-9.0.1XX]
[zip][win-x64-zip-9.0.1XX] - [Checksum][win-x64-zip-checksum-9.0.1XX] | -| **Windows x86** | [![][win-x86-badge-main]][win-x86-version-main]
[Installer][win-x86-installer-main] - [Checksum][win-x86-installer-checksum-main]
[zip][win-x86-zip-main] - [Checksum][win-x86-zip-checksum-main] | [![][win-x86-badge-9.0.2XX]][win-x86-version-9.0.2XX]
[Installer][win-x86-installer-9.0.2XX] - [Checksum][win-x86-installer-checksum-9.0.2XX]
[zip][win-x86-zip-9.0.2XX] - [Checksum][win-x86-zip-checksum-9.0.2XX] | [![][win-x86-badge-9.0.1XX]][win-x86-version-9.0.1XX]
[Installer][win-x86-installer-9.0.1XX] - [Checksum][win-x86-installer-checksum-9.0.1XX]
[zip][win-x86-zip-9.0.1XX] - [Checksum][win-x86-zip-checksum-9.0.1XX] | +| **Windows x64** | [![][win-x64-badge-main]][win-x64-version-main]
[Installer][win-x64-installer-main] - [Checksum][win-x64-installer-checksum-main]
[zip][win-x64-zip-main] - [Checksum][win-x64-zip-checksum-main] | [![][win-x64-badge-9.0.3XX]][win-x64-version-9.0.3XX]
[Installer][win-x64-installer-9.0.3XX] - [Checksum][win-x64-installer-checksum-9.0.3XX]
[zip][win-x64-zip-9.0.3XX] - [Checksum][win-x64-zip-checksum-9.0.3XX] | [![][win-x64-badge-9.0.2XX]][win-x64-version-9.0.2XX]
[Installer][win-x64-installer-9.0.2XX] - [Checksum][win-x64-installer-checksum-9.0.2XX]
[zip][win-x64-zip-9.0.2XX] - [Checksum][win-x64-zip-checksum-9.0.2XX] | +| **Windows x86** | [![][win-x86-badge-main]][win-x86-version-main]
[Installer][win-x86-installer-main] - [Checksum][win-x86-installer-checksum-main]
[zip][win-x86-zip-main] - [Checksum][win-x86-zip-checksum-main] | [![][win-x86-badge-9.0.3XX]][win-x86-version-9.0.3XX]
[Installer][win-x86-installer-9.0.3XX] - [Checksum][win-x86-installer-checksum-9.0.3XX]
[zip][win-x86-zip-9.0.3XX] - [Checksum][win-x86-zip-checksum-9.0.3XX] | [![][win-x86-badge-9.0.2XX]][win-x86-version-9.0.2XX]
[Installer][win-x86-installer-9.0.2XX] - [Checksum][win-x86-installer-checksum-9.0.2XX]
[zip][win-x86-zip-9.0.2XX] - [Checksum][win-x86-zip-checksum-9.0.2XX] | | **Windows arm** | **N/A** | **N/A** | **N/A** | -| **Windows arm64** | [![][win-arm64-badge-main]][win-arm64-version-main]
[Installer][win-arm64-installer-main] - [Checksum][win-arm64-installer-checksum-main]
[zip][win-arm64-zip-main] | [![][win-arm64-badge-9.0.2XX]][win-arm64-version-9.0.2XX]
[Installer][win-arm64-installer-9.0.2XX] - [Checksum][win-arm64-installer-checksum-9.0.2XX]
[zip][win-arm64-zip-9.0.2XX] | [![][win-arm64-badge-9.0.1XX]][win-arm64-version-9.0.1XX]
[Installer][win-arm64-installer-9.0.1XX] - [Checksum][win-arm64-installer-checksum-9.0.1XX]
[zip][win-arm64-zip-9.0.1XX] | -| **macOS x64** | [![][osx-x64-badge-main]][osx-x64-version-main]
[Installer][osx-x64-installer-main] - [Checksum][osx-x64-installer-checksum-main]
[tar.gz][osx-x64-targz-main] - [Checksum][osx-x64-targz-checksum-main] | [![][osx-x64-badge-9.0.2XX]][osx-x64-version-9.0.2XX]
[Installer][osx-x64-installer-9.0.2XX] - [Checksum][osx-x64-installer-checksum-9.0.2XX]
[tar.gz][osx-x64-targz-9.0.2XX] - [Checksum][osx-x64-targz-checksum-9.0.2XX] | [![][osx-x64-badge-9.0.1XX]][osx-x64-version-9.0.1XX]
[Installer][osx-x64-installer-9.0.1XX] - [Checksum][osx-x64-installer-checksum-9.0.1XX]
[tar.gz][osx-x64-targz-9.0.1XX] - [Checksum][osx-x64-targz-checksum-9.0.1XX] | -| **macOS arm64** | [![][osx-arm64-badge-main]][osx-arm64-version-main]
[Installer][osx-arm64-installer-main] - [Checksum][osx-arm64-installer-checksum-main]
[tar.gz][osx-arm64-targz-main] - [Checksum][osx-arm64-targz-checksum-main] | [![][osx-arm64-badge-9.0.2XX]][osx-arm64-version-9.0.2XX]
[Installer][osx-arm64-installer-9.0.2XX] - [Checksum][osx-arm64-installer-checksum-9.0.2XX]
[tar.gz][osx-arm64-targz-9.0.2XX] - [Checksum][osx-arm64-targz-checksum-9.0.2XX] | [![][osx-arm64-badge-9.0.1XX]][osx-arm64-version-9.0.1XX]
[Installer][osx-arm64-installer-9.0.1XX] - [Checksum][osx-arm64-installer-checksum-9.0.1XX]
[tar.gz][osx-arm64-targz-9.0.1XX] - [Checksum][osx-arm64-targz-checksum-9.0.1XX] | -| **Linux x64** | [![][linux-badge-main]][linux-version-main]
[DEB Installer][linux-DEB-installer-main] - [Checksum][linux-DEB-installer-checksum-main]
[RPM Installer][linux-RPM-installer-main] - [Checksum][linux-RPM-installer-checksum-main]
_see installer note below_1
[tar.gz][linux-targz-main] - [Checksum][linux-targz-checksum-main] | [![][linux-badge-9.0.2XX]][linux-version-9.0.2XX]
[DEB Installer][linux-DEB-installer-9.0.2XX] - [Checksum][linux-DEB-installer-checksum-9.0.2XX]
[RPM Installer][linux-RPM-installer-9.0.2XX] - [Checksum][linux-RPM-installer-checksum-9.0.2XX]
_see installer note below_1
[tar.gz][linux-targz-9.0.2XX] - [Checksum][linux-targz-checksum-9.0.2XX] | [![][linux-badge-9.0.1XX]][linux-version-9.0.1XX]
[DEB Installer][linux-DEB-installer-9.0.1XX] - [Checksum][linux-DEB-installer-checksum-9.0.1XX]
[RPM Installer][linux-RPM-installer-9.0.1XX] - [Checksum][linux-RPM-installer-checksum-9.0.1XX]
_see installer note below_1
[tar.gz][linux-targz-9.0.1XX] - [Checksum][linux-targz-checksum-9.0.1XX] | -| **Linux arm** | [![][linux-arm-badge-main]][linux-arm-version-main]
[tar.gz][linux-arm-targz-main] - [Checksum][linux-arm-targz-checksum-main] | [![][linux-arm-badge-9.0.2XX]][linux-arm-version-9.0.2XX]
[tar.gz][linux-arm-targz-9.0.2XX] - [Checksum][linux-arm-targz-checksum-9.0.2XX] | [![][linux-arm-badge-9.0.1XX]][linux-arm-version-9.0.1XX]
[tar.gz][linux-arm-targz-9.0.1XX] - [Checksum][linux-arm-targz-checksum-9.0.1XX] | -| **Linux arm64** | [![][linux-arm64-badge-main]][linux-arm64-version-main]
[tar.gz][linux-arm64-targz-main] - [Checksum][linux-arm64-targz-checksum-main] | [![][linux-arm64-badge-9.0.2XX]][linux-arm64-version-9.0.2XX]
[tar.gz][linux-arm64-targz-9.0.2XX] - [Checksum][linux-arm64-targz-checksum-9.0.2XX] | [![][linux-arm64-badge-9.0.1XX]][linux-arm64-version-9.0.1XX]
[tar.gz][linux-arm64-targz-9.0.1XX] - [Checksum][linux-arm64-targz-checksum-9.0.1XX] | -| **Linux-musl-x64** | [![][linux-musl-x64-badge-main]][linux-musl-x64-version-main]
[tar.gz][linux-musl-x64-targz-main] - [Checksum][linux-musl-x64-targz-checksum-main] | [![][linux-musl-x64-badge-9.0.2XX]][linux-musl-x64-version-9.0.2XX]
[tar.gz][linux-musl-x64-targz-9.0.2XX] - [Checksum][linux-musl-x64-targz-checksum-9.0.2XX] | [![][linux-musl-x64-badge-9.0.1XX]][linux-musl-x64-version-9.0.1XX]
[tar.gz][linux-musl-x64-targz-9.0.1XX] - [Checksum][linux-musl-x64-targz-checksum-9.0.1XX] | -| **Linux-musl-arm** | [![][linux-musl-arm-badge-main]][linux-musl-arm-version-main]
[tar.gz][linux-musl-arm-targz-main] - [Checksum][linux-musl-arm-targz-checksum-main] | [![][linux-musl-arm-badge-9.0.2XX]][linux-musl-arm-version-9.0.2XX]
[tar.gz][linux-musl-arm-targz-9.0.2XX] - [Checksum][linux-musl-arm-targz-checksum-9.0.2XX] | [![][linux-musl-arm-badge-9.0.1XX]][linux-musl-arm-version-9.0.1XX]
[tar.gz][linux-musl-arm-targz-9.0.1XX] - [Checksum][linux-musl-arm-targz-checksum-9.0.1XX] | -| **Linux-musl-arm64** | [![][linux-musl-arm64-badge-main]][linux-musl-arm64-version-main]
[tar.gz][linux-musl-arm64-targz-main] - [Checksum][linux-musl-arm64-targz-checksum-main] | [![][linux-musl-arm64-badge-9.0.2XX]][linux-musl-arm64-version-9.0.2XX]
[tar.gz][linux-musl-arm64-targz-9.0.2XX] - [Checksum][linux-musl-arm64-targz-checksum-9.0.2XX] | [![][linux-musl-arm64-badge-9.0.1XX]][linux-musl-arm64-version-9.0.1XX]
[tar.gz][linux-musl-arm64-targz-9.0.1XX] - [Checksum][linux-musl-arm64-targz-checksum-9.0.1XX] | +| **Windows arm64** | [![][win-arm64-badge-main]][win-arm64-version-main]
[Installer][win-arm64-installer-main] - [Checksum][win-arm64-installer-checksum-main]
[zip][win-arm64-zip-main] | [![][win-arm64-badge-9.0.3XX]][win-arm64-version-9.0.3XX]
[Installer][win-arm64-installer-9.0.3XX] - [Checksum][win-arm64-installer-checksum-9.0.3XX]
[zip][win-arm64-zip-9.0.3XX] | [![][win-arm64-badge-9.0.2XX]][win-arm64-version-9.0.2XX]
[Installer][win-arm64-installer-9.0.2XX] - [Checksum][win-arm64-installer-checksum-9.0.2XX]
[zip][win-arm64-zip-9.0.2XX] | +| **macOS x64** | [![][osx-x64-badge-main]][osx-x64-version-main]
[Installer][osx-x64-installer-main] - [Checksum][osx-x64-installer-checksum-main]
[tar.gz][osx-x64-targz-main] - [Checksum][osx-x64-targz-checksum-main] | [![][osx-x64-badge-9.0.3XX]][osx-x64-version-9.0.3XX]
[Installer][osx-x64-installer-9.0.3XX] - [Checksum][osx-x64-installer-checksum-9.0.3XX]
[tar.gz][osx-x64-targz-9.0.3XX] - [Checksum][osx-x64-targz-checksum-9.0.3XX] | [![][osx-x64-badge-9.0.2XX]][osx-x64-version-9.0.2XX]
[Installer][osx-x64-installer-9.0.2XX] - [Checksum][osx-x64-installer-checksum-9.0.2XX]
[tar.gz][osx-x64-targz-9.0.2XX] - [Checksum][osx-x64-targz-checksum-9.0.2XX] | +| **macOS arm64** | [![][osx-arm64-badge-main]][osx-arm64-version-main]
[Installer][osx-arm64-installer-main] - [Checksum][osx-arm64-installer-checksum-main]
[tar.gz][osx-arm64-targz-main] - [Checksum][osx-arm64-targz-checksum-main] | [![][osx-arm64-badge-9.0.3XX]][osx-arm64-version-9.0.3XX]
[Installer][osx-arm64-installer-9.0.3XX] - [Checksum][osx-arm64-installer-checksum-9.0.3XX]
[tar.gz][osx-arm64-targz-9.0.3XX] - [Checksum][osx-arm64-targz-checksum-9.0.3XX] | [![][osx-arm64-badge-9.0.2XX]][osx-arm64-version-9.0.2XX]
[Installer][osx-arm64-installer-9.0.2XX] - [Checksum][osx-arm64-installer-checksum-9.0.2XX]
[tar.gz][osx-arm64-targz-9.0.2XX] - [Checksum][osx-arm64-targz-checksum-9.0.2XX] | +| **Linux x64** | [![][linux-badge-main]][linux-version-main]
[DEB Installer][linux-DEB-installer-main] - [Checksum][linux-DEB-installer-checksum-main]
[RPM Installer][linux-RPM-installer-main] - [Checksum][linux-RPM-installer-checksum-main]
_see installer note below_1
[tar.gz][linux-targz-main] - [Checksum][linux-targz-checksum-main] | [![][linux-badge-9.0.3XX]][linux-version-9.0.3XX]
[DEB Installer][linux-DEB-installer-9.0.3XX] - [Checksum][linux-DEB-installer-checksum-9.0.3XX]
[RPM Installer][linux-RPM-installer-9.0.3XX] - [Checksum][linux-RPM-installer-checksum-9.0.3XX]
_see installer note below_1
[tar.gz][linux-targz-9.0.3XX] - [Checksum][linux-targz-checksum-9.0.3XX] | [![][linux-badge-9.0.2XX]][linux-version-9.0.2XX]
[DEB Installer][linux-DEB-installer-9.0.2XX] - [Checksum][linux-DEB-installer-checksum-9.0.2XX]
[RPM Installer][linux-RPM-installer-9.0.2XX] - [Checksum][linux-RPM-installer-checksum-9.0.2XX]
_see installer note below_1
[tar.gz][linux-targz-9.0.2XX] - [Checksum][linux-targz-checksum-9.0.2XX] | +| **Linux arm** | [![][linux-arm-badge-main]][linux-arm-version-main]
[tar.gz][linux-arm-targz-main] - [Checksum][linux-arm-targz-checksum-main] | [![][linux-arm-badge-9.0.3XX]][linux-arm-version-9.0.3XX]
[tar.gz][linux-arm-targz-9.0.3XX] - [Checksum][linux-arm-targz-checksum-9.0.3XX] | [![][linux-arm-badge-9.0.2XX]][linux-arm-version-9.0.2XX]
[tar.gz][linux-arm-targz-9.0.2XX] - [Checksum][linux-arm-targz-checksum-9.0.2XX] | +| **Linux arm64** | [![][linux-arm64-badge-main]][linux-arm64-version-main]
[tar.gz][linux-arm64-targz-main] - [Checksum][linux-arm64-targz-checksum-main] | [![][linux-arm64-badge-9.0.3XX]][linux-arm64-version-9.0.3XX]
[tar.gz][linux-arm64-targz-9.0.3XX] - [Checksum][linux-arm64-targz-checksum-9.0.3XX] | [![][linux-arm64-badge-9.0.2XX]][linux-arm64-version-9.0.2XX]
[tar.gz][linux-arm64-targz-9.0.2XX] - [Checksum][linux-arm64-targz-checksum-9.0.2XX] | +| **Linux-musl-x64** | [![][linux-musl-x64-badge-main]][linux-musl-x64-version-main]
[tar.gz][linux-musl-x64-targz-main] - [Checksum][linux-musl-x64-targz-checksum-main] | [![][linux-musl-x64-badge-9.0.3XX]][linux-musl-x64-version-9.0.3XX]
[tar.gz][linux-musl-x64-targz-9.0.3XX] - [Checksum][linux-musl-x64-targz-checksum-9.0.3XX] | [![][linux-musl-x64-badge-9.0.2XX]][linux-musl-x64-version-9.0.2XX]
[tar.gz][linux-musl-x64-targz-9.0.2XX] - [Checksum][linux-musl-x64-targz-checksum-9.0.2XX] | +| **Linux-musl-arm** | [![][linux-musl-arm-badge-main]][linux-musl-arm-version-main]
[tar.gz][linux-musl-arm-targz-main] - [Checksum][linux-musl-arm-targz-checksum-main] | [![][linux-musl-arm-badge-9.0.3XX]][linux-musl-arm-version-9.0.3XX]
[tar.gz][linux-musl-arm-targz-9.0.3XX] - [Checksum][linux-musl-arm-targz-checksum-9.0.3XX] | [![][linux-musl-arm-badge-9.0.2XX]][linux-musl-arm-version-9.0.2XX]
[tar.gz][linux-musl-arm-targz-9.0.2XX] - [Checksum][linux-musl-arm-targz-checksum-9.0.2XX] | +| **Linux-musl-arm64** | [![][linux-musl-arm64-badge-main]][linux-musl-arm64-version-main]
[tar.gz][linux-musl-arm64-targz-main] - [Checksum][linux-musl-arm64-targz-checksum-main] | [![][linux-musl-arm64-badge-9.0.3XX]][linux-musl-arm64-version-9.0.3XX]
[tar.gz][linux-musl-arm64-targz-9.0.3XX] - [Checksum][linux-musl-arm64-targz-checksum-9.0.3XX] | [![][linux-musl-arm64-badge-9.0.2XX]][linux-musl-arm64-version-9.0.2XX]
[tar.gz][linux-musl-arm64-targz-9.0.2XX] - [Checksum][linux-musl-arm64-targz-checksum-9.0.2XX] | | **RHEL 6** | **N/A** | **N/A** | **N/A** | Reference notes: @@ -25,221 +25,236 @@ Reference notes: [win-x64-badge-main]: https://aka.ms/dotnet/10.0.1xx/daily/win_x64_Release_version_badge.svg?no-cache [win-x64-version-main]: https://aka.ms/dotnet/10.0.1xx/daily/productCommit-win-x64.txt [win-x64-installer-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-x64.exe -[win-x64-installer-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-x64.exe.sha512 +[win-x64-installer-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-x64.exe.sha [win-x64-zip-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-x64.zip -[win-x64-zip-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-x64.zip.sha512 +[win-x64-zip-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-x64.zip.sha + +[win-x64-badge-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/win_x64_Release_version_badge.svg?no-cache +[win-x64-version-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/productCommit-win-x64.txt +[win-x64-installer-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-win-x64.exe +[win-x64-installer-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-win-x64.exe.sha +[win-x64-zip-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-win-x64.zip +[win-x64-zip-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-win-x64.zip.sha [win-x64-badge-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/win_x64_Release_version_badge.svg?no-cache [win-x64-version-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/productCommit-win-x64.txt [win-x64-installer-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-x64.exe -[win-x64-installer-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-x64.exe.sha512 +[win-x64-installer-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-x64.exe.sha [win-x64-zip-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-x64.zip -[win-x64-zip-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-x64.zip.sha512 - -[win-x64-badge-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/win_x64_Release_version_badge.svg?no-cache -[win-x64-version-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/productCommit-win-x64.txt -[win-x64-installer-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-win-x64.exe -[win-x64-installer-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-win-x64.exe.sha512 -[win-x64-zip-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-win-x64.zip -[win-x64-zip-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-win-x64.zip.sha512 +[win-x64-zip-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-x64.zip.sha [win-x86-badge-main]: https://aka.ms/dotnet/10.0.1xx/daily/win_x86_Release_version_badge.svg?no-cache [win-x86-version-main]: https://aka.ms/dotnet/10.0.1xx/daily/productCommit-win-x86.txt [win-x86-installer-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-x86.exe -[win-x86-installer-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-x86.exe.sha512 +[win-x86-installer-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-x86.exe.sha [win-x86-zip-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-x86.zip -[win-x86-zip-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-x86.zip.sha512 +[win-x86-zip-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-x86.zip.sha + +[win-x86-badge-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/win_x86_Release_version_badge.svg?no-cache +[win-x86-version-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/productCommit-win-x86.txt +[win-x86-installer-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-win-x86.exe +[win-x86-installer-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-win-x86.exe.sha +[win-x86-zip-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-win-x86.zip +[win-x86-zip-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-win-x86.zip.sha [win-x86-badge-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/win_x86_Release_version_badge.svg?no-cache [win-x86-version-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/productCommit-win-x86.txt [win-x86-installer-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-x86.exe -[win-x86-installer-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-x86.exe.sha512 +[win-x86-installer-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-x86.exe.sha [win-x86-zip-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-x86.zip -[win-x86-zip-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-x86.zip.sha512 - -[win-x86-badge-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/win_x86_Release_version_badge.svg?no-cache -[win-x86-version-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/productCommit-win-x86.txt -[win-x86-installer-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-win-x86.exe -[win-x86-installer-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-win-x86.exe.sha512 -[win-x86-zip-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-win-x86.zip -[win-x86-zip-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-win-x86.zip.sha512 +[win-x86-zip-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-x86.zip.sha [osx-x64-badge-main]: https://aka.ms/dotnet/10.0.1xx/daily/osx_x64_Release_version_badge.svg?no-cache [osx-x64-version-main]: https://aka.ms/dotnet/10.0.1xx/daily/productCommit-osx-x64.txt [osx-x64-installer-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-osx-x64.pkg -[osx-x64-installer-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-osx-x64.pkg.sha512 +[osx-x64-installer-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-osx-x64.pkg.sha [osx-x64-targz-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-osx-x64.tar.gz -[osx-x64-targz-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-osx-x64.pkg.tar.gz.sha512 +[osx-x64-targz-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-osx-x64.pkg.tar.gz.sha + +[osx-x64-badge-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/osx_x64_Release_version_badge.svg?no-cache +[osx-x64-version-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/productCommit-osx-x64.txt +[osx-x64-installer-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-osx-x64.pkg +[osx-x64-installer-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-osx-x64.pkg.sha +[osx-x64-targz-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-osx-x64.tar.gz +[osx-x64-targz-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-osx-x64.pkg.tar.gz.sha [osx-x64-badge-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/osx_x64_Release_version_badge.svg?no-cache [osx-x64-version-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/productCommit-osx-x64.txt [osx-x64-installer-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-osx-x64.pkg -[osx-x64-installer-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-osx-x64.pkg.sha512 +[osx-x64-installer-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-osx-x64.pkg.sha [osx-x64-targz-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-osx-x64.tar.gz -[osx-x64-targz-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-osx-x64.pkg.tar.gz.sha512 - -[osx-x64-badge-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/osx_x64_Release_version_badge.svg?no-cache -[osx-x64-version-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/productCommit-osx-x64.txt -[osx-x64-installer-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-osx-x64.pkg -[osx-x64-installer-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-osx-x64.pkg.sha512 -[osx-x64-targz-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-osx-x64.tar.gz -[osx-x64-targz-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-osx-x64.pkg.tar.gz.sha512 +[osx-x64-targz-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-osx-x64.pkg.tar.gz.sha [osx-arm64-badge-main]: https://aka.ms/dotnet/10.0.1xx/daily/osx_arm64_Release_version_badge.svg?no-cache [osx-arm64-version-main]: https://aka.ms/dotnet/10.0.1xx/daily/productCommit-osx-arm64.txt [osx-arm64-installer-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-osx-arm64.pkg -[osx-arm64-installer-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-osx-arm64.pkg.sha512 +[osx-arm64-installer-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-osx-arm64.pkg.sha [osx-arm64-targz-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-osx-arm64.tar.gz -[osx-arm64-targz-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-osx-arm64.pkg.tar.gz.sha512 +[osx-arm64-targz-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-osx-arm64.pkg.tar.gz.sha + +[osx-arm64-badge-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/osx_arm64_Release_version_badge.svg?no-cache +[osx-arm64-version-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/productCommit-osx-arm64.txt +[osx-arm64-installer-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-osx-arm64.pkg +[osx-arm64-installer-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-osx-arm64.pkg.sha +[osx-arm64-targz-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-osx-arm64.tar.gz +[osx-arm64-targz-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-osx-arm64.pkg.tar.gz.sha [osx-arm64-badge-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/osx_arm64_Release_version_badge.svg?no-cache [osx-arm64-version-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/productCommit-osx-arm64.txt [osx-arm64-installer-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-osx-arm64.pkg -[osx-arm64-installer-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-osx-arm64.pkg.sha512 +[osx-arm64-installer-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-osx-arm64.pkg.sha [osx-arm64-targz-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-osx-arm64.tar.gz -[osx-arm64-targz-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-osx-arm64.pkg.tar.gz.sha512 - -[osx-arm64-badge-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/osx_arm64_Release_version_badge.svg?no-cache -[osx-arm64-version-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/productCommit-osx-arm64.txt -[osx-arm64-installer-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-osx-arm64.pkg -[osx-arm64-installer-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-osx-arm64.pkg.sha512 -[osx-arm64-targz-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-osx-arm64.tar.gz -[osx-arm64-targz-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-osx-arm64.pkg.tar.gz.sha512 +[osx-arm64-targz-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-osx-arm64.pkg.tar.gz.sha [linux-badge-main]: https://aka.ms/dotnet/10.0.1xx/daily/linux_x64_Release_version_badge.svg?no-cache [linux-version-main]: https://aka.ms/dotnet/10.0.1xx/daily/productCommit-linux-x64.txt [linux-DEB-installer-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-x64.deb -[linux-DEB-installer-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-x64.deb.sha512 +[linux-DEB-installer-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-x64.deb.sha [linux-RPM-installer-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-x64.rpm -[linux-RPM-installer-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-x64.rpm.sha512 +[linux-RPM-installer-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-x64.rpm.sha [linux-targz-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-linux-x64.tar.gz -[linux-targz-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-linux-x64.tar.gz.sha512 +[linux-targz-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-linux-x64.tar.gz.sha + +[linux-badge-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/linux_x64_Release_version_badge.svg?no-cache +[linux-version-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/productCommit-linux-x64.txt +[linux-DEB-installer-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-x64.deb +[linux-DEB-installer-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-x64.deb.sha +[linux-RPM-installer-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-x64.rpm +[linux-RPM-installer-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-x64.rpm.sha +[linux-targz-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-linux-x64.tar.gz +[linux-targz-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-linux-x64.tar.gz.sha [linux-badge-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/linux_x64_Release_version_badge.svg?no-cache [linux-version-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/productCommit-linux-x64.txt [linux-DEB-installer-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-x64.deb -[linux-DEB-installer-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-x64.deb.sha512 +[linux-DEB-installer-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-x64.deb.sha [linux-RPM-installer-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-x64.rpm -[linux-RPM-installer-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-x64.rpm.sha512 +[linux-RPM-installer-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-x64.rpm.sha [linux-targz-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-linux-x64.tar.gz -[linux-targz-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-linux-x64.tar.gz.sha512 - -[linux-badge-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/linux_x64_Release_version_badge.svg?no-cache -[linux-version-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/productCommit-linux-x64.txt -[linux-DEB-installer-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-x64.deb -[linux-DEB-installer-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-x64.deb.sha512 -[linux-RPM-installer-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-x64.rpm -[linux-RPM-installer-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-x64.rpm.sha512 -[linux-targz-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-linux-x64.tar.gz -[linux-targz-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-linux-x64.tar.gz.sha512 +[linux-targz-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-linux-x64.tar.gz.sha [linux-arm-badge-main]: https://aka.ms/dotnet/10.0.1xx/daily/linux_arm_Release_version_badge.svg?no-cache [linux-arm-version-main]: https://aka.ms/dotnet/10.0.1xx/daily/productCommit-linux-arm.txt [linux-arm-targz-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-linux-arm.tar.gz -[linux-arm-targz-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-linux-arm.tar.gz.sha512 +[linux-arm-targz-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-linux-arm.tar.gz.sha + +[linux-arm-badge-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/linux_arm_Release_version_badge.svg?no-cache +[linux-arm-version-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/productCommit-linux-arm.txt +[linux-arm-targz-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-linux-arm.tar.gz +[linux-arm-targz-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-linux-arm.tar.gz.sha [linux-arm-badge-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/linux_arm_Release_version_badge.svg?no-cache [linux-arm-version-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/productCommit-linux-arm.txt [linux-arm-targz-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-linux-arm.tar.gz -[linux-arm-targz-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-linux-arm.tar.gz.sha512 - -[linux-arm-badge-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/linux_arm_Release_version_badge.svg?no-cache -[linux-arm-version-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/productCommit-linux-arm.txt -[linux-arm-targz-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-linux-arm.tar.gz -[linux-arm-targz-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-linux-arm.tar.gz.sha512 +[linux-arm-targz-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-linux-arm.tar.gz.sha [linux-arm64-badge-main]: https://aka.ms/dotnet/10.0.1xx/daily/linux_arm64_Release_version_badge.svg?no-cache [linux-arm64-version-main]: https://aka.ms/dotnet/10.0.1xx/daily/productCommit-linux-arm64.txt [linux-arm64-targz-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-linux-arm64.tar.gz -[linux-arm64-targz-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-linux-arm64.tar.gz.sha512 +[linux-arm64-targz-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-linux-arm64.tar.gz.sha + +[linux-arm64-badge-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/linux_arm64_Release_version_badge.svg?no-cache +[linux-arm64-version-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/productCommit-linux-arm64.txt +[linux-arm64-targz-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-linux-arm64.tar.gz +[linux-arm64-targz-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-linux-arm64.tar.gz.sha [linux-arm64-badge-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/linux_arm64_Release_version_badge.svg?no-cache [linux-arm64-version-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/productCommit-linux-arm64.txt [linux-arm64-targz-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-linux-arm64.tar.gz -[linux-arm64-targz-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-linux-arm64.tar.gz.sha512 +[linux-arm64-targz-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-linux-arm64.tar.gz.sha + +[rhel-6-badge-main]: https://aka.ms/dotnet/10.0.1xx/daily/rhel.6_x64_Release_version_badge.svg?no-cache +[rhel-6-version-main]: https://aka.ms/dotnet/10.0.1xx/daily/productCommit-rhel.6-x64.txt +[rhel-6-targz-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-rhel.6-x64.tar.gz +[rhel-6-targz-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-rhel.6-x64.tar.gz.sha + +[rhel-6-badge-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/rhel.6_x64_Release_version_badge.svg?no-cache +[rhel-6-version-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/productCommit-rhel.6-x64.txt +[rhel-6-targz-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-rhel.6-x64.tar.gz +[rhel-6-targz-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-rhel.6-x64.tar.gz.sha -[linux-arm64-badge-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/linux_arm64_Release_version_badge.svg?no-cache -[linux-arm64-version-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/productCommit-linux-arm64.txt -[linux-arm64-targz-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-linux-arm64.tar.gz -[linux-arm64-targz-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-linux-arm64.tar.gz.sha512 +[rhel-6-badge-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/rhel.6_x64_Release_version_badge.svg?no-cache +[rhel-6-version-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/productCommit-rhel.6-x64.txt +[rhel-6-targz-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-rhel.6-x64.tar.gz +[rhel-6-targz-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-rhel.6-x64.tar.gz.sha [linux-musl-x64-badge-main]: https://aka.ms/dotnet/10.0.1xx/daily/linux_musl_x64_Release_version_badge.svg?no-cache [linux-musl-x64-version-main]: https://aka.ms/dotnet/10.0.1xx/daily/productCommit-linux-musl-x64.txt [linux-musl-x64-targz-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-linux-musl-x64.tar.gz -[linux-musl-x64-targz-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-linux-musl-x64.tar.gz.sha512 +[linux-musl-x64-targz-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-linux-musl-x64.tar.gz.sha + +[linux-musl-x64-badge-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/linux_musl_x64_Release_version_badge.svg?no-cache +[linux-musl-x64-version-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/productCommit-linux-musl-x64.txt +[linux-musl-x64-targz-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-linux-musl-x64.tar.gz +[linux-musl-x64-targz-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-linux-musl-x64.tar.gz.sha [linux-musl-x64-badge-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/linux_musl_x64_Release_version_badge.svg?no-cache [linux-musl-x64-version-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/productCommit-linux-musl-x64.txt [linux-musl-x64-targz-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-linux-musl-x64.tar.gz -[linux-musl-x64-targz-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-linux-musl-x64.tar.gz.sha512 - -[linux-musl-x64-badge-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/linux_musl_x64_Release_version_badge.svg?no-cache -[linux-musl-x64-version-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/productCommit-linux-musl-x64.txt -[linux-musl-x64-targz-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-linux-musl-x64.tar.gz -[linux-musl-x64-targz-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-linux-musl-x64.tar.gz.sha512 +[linux-musl-x64-targz-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-linux-musl-x64.tar.gz.sha [linux-musl-arm-badge-main]: https://aka.ms/dotnet/10.0.1xx/daily/linux_musl_arm_Release_version_badge.svg?no-cache [linux-musl-arm-version-main]: https://aka.ms/dotnet/10.0.1xx/daily/productCommit-linux-musl-arm.txt [linux-musl-arm-targz-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-linux-musl-arm.tar.gz -[linux-musl-arm-targz-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-linux-musl-arm.tar.gz.sha512 +[linux-musl-arm-targz-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-linux-musl-arm.tar.gz.sha + +[linux-musl-arm-badge-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/linux_musl_arm_Release_version_badge.svg?no-cache +[linux-musl-arm-version-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/productCommit-linux-musl-arm.txt +[linux-musl-arm-targz-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-linux-musl-arm.tar.gz +[linux-musl-arm-targz-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-linux-musl-arm.tar.gz.sha [linux-musl-arm-badge-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/linux_musl_arm_Release_version_badge.svg?no-cache [linux-musl-arm-version-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/productCommit-linux-musl-arm.txt [linux-musl-arm-targz-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-linux-musl-arm.tar.gz -[linux-musl-arm-targz-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-linux-musl-arm.tar.gz.sha512 - -[linux-musl-arm-badge-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/linux_musl_arm_Release_version_badge.svg?no-cache -[linux-musl-arm-version-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/productCommit-linux-musl-arm.txt -[linux-musl-arm-targz-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-linux-musl-arm.tar.gz -[linux-musl-arm-targz-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-linux-musl-arm.tar.gz.sha512 +[linux-musl-arm-targz-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-linux-musl-arm.tar.gz.sha [linux-musl-arm64-badge-main]: https://aka.ms/dotnet/10.0.1xx/daily/linux_musl_arm64_Release_version_badge.svg?no-cache [linux-musl-arm64-version-main]: https://aka.ms/dotnet/10.0.1xx/daily/productCommit-linux-musl-arm64.txt [linux-musl-arm64-targz-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-linux-musl-arm64.tar.gz -[linux-musl-arm64-targz-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-linux-musl-arm64.tar.gz.sha512 +[linux-musl-arm64-targz-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-linux-musl-arm64.tar.gz.sha + +[linux-musl-arm64-badge-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/linux_musl_arm64_Release_version_badge.svg?no-cache +[linux-musl-arm64-version-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/productCommit-linux-musl-arm64.txt +[linux-musl-arm64-targz-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-linux-musl-arm64.tar.gz +[linux-musl-arm64-targz-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-linux-musl-arm64.tar.gz.sha [linux-musl-arm64-badge-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/linux_musl_arm64_Release_version_badge.svg?no-cache [linux-musl-arm64-version-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/productCommit-linux-musl-arm64.txt [linux-musl-arm64-targz-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-linux-musl-arm64.tar.gz -[linux-musl-arm64-targz-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-linux-musl-arm64.tar.gz.sha512 - -[linux-musl-arm64-badge-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/linux_musl_arm64_Release_version_badge.svg?no-cache -[linux-musl-arm64-version-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/productCommit-linux-musl-arm64.txt -[linux-musl-arm64-targz-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-linux-musl-arm64.tar.gz -[linux-musl-arm64-targz-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-linux-musl-arm64.tar.gz.sha512 +[linux-musl-arm64-targz-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-linux-musl-arm64.tar.gz.sha [win-arm-badge-main]: https://aka.ms/dotnet/10.0.1xx/daily/win_arm_Release_version_badge.svg?no-cache [win-arm-version-main]: https://aka.ms/dotnet/10.0.1xx/daily/productCommit-win-arm.txt [win-arm-zip-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-arm.zip -[win-arm-zip-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-arm.zip.sha512 +[win-arm-zip-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-arm.zip.sha + +[win-arm-badge-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/win_arm_Release_version_badge.svg?no-cache +[win-arm-version-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/productCommit-win-arm.txt +[win-arm-zip-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-win-arm.zip +[win-arm-zip-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-win-arm.zip.sha [win-arm-badge-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/win_arm_Release_version_badge.svg?no-cache [win-arm-version-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/productCommit-win-arm.txt [win-arm-zip-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-arm.zip -[win-arm-zip-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-arm.zip.sha512 - -[win-arm-badge-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/win_arm_Release_version_badge.svg?no-cache -[win-arm-version-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/productCommit-win-arm.txt -[win-arm-zip-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-win-arm.zip -[win-arm-zip-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-win-arm.zip.sha512 +[win-arm-zip-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-arm.zip.sha [win-arm64-badge-main]: https://aka.ms/dotnet/10.0.1xx/daily/win_arm64_Release_version_badge.svg?no-cache [win-arm64-version-main]: https://aka.ms/dotnet/10.0.1xx/daily/productCommit-win-arm64.txt [win-arm64-installer-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-arm64.exe -[win-arm64-installer-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-arm64.exe.sha512 +[win-arm64-installer-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-arm64.exe.sha [win-arm64-zip-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-arm64.zip -[win-arm64-zip-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-arm64.zip.sha512 +[win-arm64-zip-checksum-main]: https://aka.ms/dotnet/10.0.1xx/daily/dotnet-sdk-win-arm64.zip.sha + +[win-arm64-badge-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/win_arm64_Release_version_badge.svg?no-cache +[win-arm64-version-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/productCommit-win-arm64.txt +[win-arm64-installer-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-win-arm64.exe +[win-arm64-installer-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-win-arm64.exe.sha +[win-arm64-zip-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-win-arm64.zip +[win-arm64-zip-checksum-9.0.3XX]: https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-win-arm64.zip.sha [win-arm64-badge-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/win_arm64_Release_version_badge.svg?no-cache [win-arm64-version-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/productCommit-win-arm64.txt [win-arm64-installer-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-arm64.exe -[win-arm64-installer-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-arm64.exe.sha512 +[win-arm64-installer-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-arm64.exe.sha [win-arm64-zip-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-arm64.zip -[win-arm64-zip-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-arm64.zip.sha512 - -[win-arm64-badge-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/win_arm64_Release_version_badge.svg?no-cache -[win-arm64-version-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/productCommit-win-arm64.txt -[win-arm64-installer-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-win-arm64.exe -[win-arm64-installer-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-win-arm64.exe.sha512 -[win-arm64-zip-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-win-arm64.zip -[win-arm64-zip-checksum-9.0.1XX]: https://aka.ms/dotnet/9.0.1xx/daily/dotnet-sdk-win-arm64.zip.sha512 +[win-arm64-zip-checksum-9.0.2XX]: https://aka.ms/dotnet/9.0.2xx/daily/dotnet-sdk-win-arm64.zip.sha diff --git a/eng/AfterSigning.targets b/eng/AfterSigning.targets deleted file mode 100644 index 8e7aa3cf435c..000000000000 --- a/eng/AfterSigning.targets +++ /dev/null @@ -1,23 +0,0 @@ - - - - <_SuppressSdkImports>false - - - - - - - - - - - - %(FullPath).sha512 - - - - - - - diff --git a/eng/Publishing.props b/eng/Publishing.props index bc7ff4ee664a..e4a04a4a7351 100644 --- a/eng/Publishing.props +++ b/eng/Publishing.props @@ -6,239 +6,24 @@ true - - Sdk - $(Product) - assets/$(Product) - -BuildPass$(DotNetBuildPass) - $(OS)-$(PlatformName)-SdkAssets$(SdkAssetManifestBuildPass).xml - $(ArtifactsLogDir)AssetManifest\$(SdkAssetManifestFileName) - - true - - false - true - - - - - $(SYSTEM_TEAMFOUNDATIONCOLLECTIONURI) - - - $(CollectionUri.Split('/')[3]) - - - $(CollectionUri.Split('.')[0].Split('/')[2]) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $(PublishDependsOnTargets);_ResolvePublishFSharpNuGetPackages - - - - - Shipping - Release - - - - - - - - - - - - - - - - - - - - - - - - - $(AGENT_OS) - $(OS) - $(AssetManifestOS)-$(SYSTEM_PHASENAME) - $(AssetManifestOS) - $(AssetManifestOS)-$(Architecture) - $(BaseAssetManifestFileName)-installers$(SdkAssetManifestBuildPass) - - $(ArtifactsLogDir)AssetManifest\$(InstallersAssetManifestFileName).xml + To achieve this, we find the FSharp compiler package, then the stable or non-stable FSharp.Core and Compiler service + package contained within, depending on the stability switch of the SDK. The SDK then treats these packages as its own outputs, + which means they get automatically pushed on release day. + + These packages have already been signed by the FSharp build so we don't need to re-include them for signing. --> + + Shipping + Release + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - $(BlobStoragePartialRelativePath)/$(FullNugetVersion)/$([System.String]::Copy('%(Filename)%(Extension)')) - DotNetReleaseShipping=true - - - - $(BlobStoragePartialRelativePath)/$(FullNugetVersion)/$([System.String]::Copy('%(Filename)%(Extension)')) - NonShipping=true - - - - $(BlobStoragePartialRelativePath)/$(FullNugetVersion)/$([System.String]::Copy('%(Filename)%(Extension)')) - DotNetReleaseShipping=true - - - - - - - - - - - - - - - - - diff --git a/eng/Signing.props b/eng/Signing.props index d21cce9aa953..6eb14f2e0ba3 100644 --- a/eng/Signing.props +++ b/eng/Signing.props @@ -1,21 +1,14 @@ - - - - - - - + + + Sdk/$([System.IO.File]::ReadAllText('$(ArtifactsTmpDir)FullNugetVersion.version').Trim()) + true + 3PartySHA2 MicrosoftDotNet500 - - - true - true - true @@ -83,8 +76,47 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %(FullPath).sha512 + + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index abe69229760d..bbb52c0f6715 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,60 +1,60 @@ - + https://github.com/dotnet/templating - 6a6c089abc661bd597b32a63e41a9bd2a011950e + 7137d45fe29466e53caadc374472912811f6522e - + https://github.com/dotnet/templating - 6a6c089abc661bd597b32a63e41a9bd2a011950e + 7137d45fe29466e53caadc374472912811f6522e - + https://github.com/dotnet/templating - 6a6c089abc661bd597b32a63e41a9bd2a011950e + 7137d45fe29466e53caadc374472912811f6522e - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd @@ -73,341 +73,345 @@ 0de3165cb0d56323b6caaf8e9916d4d9e72da32d - + https://github.com/dotnet/msbuild - c81c498d4efee2ac3360bbfb9f161016a5969994 + 291a8108761ed347562228f2f8f25477996a5a93 - + https://github.com/dotnet/msbuild - c81c498d4efee2ac3360bbfb9f161016a5969994 + 291a8108761ed347562228f2f8f25477996a5a93 - + https://github.com/dotnet/msbuild - c81c498d4efee2ac3360bbfb9f161016a5969994 + 291a8108761ed347562228f2f8f25477996a5a93 - + https://github.com/dotnet/fsharp - f4710e30f913b910ab468f0ca19dc67b7e561727 + 387f04cb6675c984036a64c9bb768ac6f00e06f9 - + https://github.com/dotnet/fsharp - f4710e30f913b910ab468f0ca19dc67b7e561727 + 387f04cb6675c984036a64c9bb768ac6f00e06f9 - + https://github.com/dotnet/roslyn - 6f7613e4d34d835667c90c6b09fbac1240f77bb1 + 6908aead3a8b313798c381d5e435e9e6068301a7 - + https://github.com/dotnet/roslyn - 6f7613e4d34d835667c90c6b09fbac1240f77bb1 + 6908aead3a8b313798c381d5e435e9e6068301a7 - + https://github.com/dotnet/roslyn - 6f7613e4d34d835667c90c6b09fbac1240f77bb1 + 6908aead3a8b313798c381d5e435e9e6068301a7 - + https://github.com/dotnet/roslyn - 6f7613e4d34d835667c90c6b09fbac1240f77bb1 + 6908aead3a8b313798c381d5e435e9e6068301a7 - + https://github.com/dotnet/roslyn - 6f7613e4d34d835667c90c6b09fbac1240f77bb1 + 6908aead3a8b313798c381d5e435e9e6068301a7 - + https://github.com/dotnet/roslyn - 6f7613e4d34d835667c90c6b09fbac1240f77bb1 + 6908aead3a8b313798c381d5e435e9e6068301a7 - + https://github.com/dotnet/roslyn - 6f7613e4d34d835667c90c6b09fbac1240f77bb1 + 6908aead3a8b313798c381d5e435e9e6068301a7 - + https://github.com/dotnet/roslyn - 6f7613e4d34d835667c90c6b09fbac1240f77bb1 + 6908aead3a8b313798c381d5e435e9e6068301a7 - + https://github.com/dotnet/roslyn - 6f7613e4d34d835667c90c6b09fbac1240f77bb1 + 6908aead3a8b313798c381d5e435e9e6068301a7 - + + https://github.com/dotnet/roslyn + 6908aead3a8b313798c381d5e435e9e6068301a7 + + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/nuget/nuget.client - c4b26195ee5a77e70b2ea5fd50db87d6a9194c24 + a4a2e3f31ddc2adb52ebd3204ea6f650d89caf3f - + https://github.com/nuget/nuget.client - c4b26195ee5a77e70b2ea5fd50db87d6a9194c24 + a4a2e3f31ddc2adb52ebd3204ea6f650d89caf3f - + https://github.com/nuget/nuget.client - c4b26195ee5a77e70b2ea5fd50db87d6a9194c24 + a4a2e3f31ddc2adb52ebd3204ea6f650d89caf3f - + https://github.com/nuget/nuget.client - c4b26195ee5a77e70b2ea5fd50db87d6a9194c24 + a4a2e3f31ddc2adb52ebd3204ea6f650d89caf3f - + https://github.com/nuget/nuget.client - c4b26195ee5a77e70b2ea5fd50db87d6a9194c24 + a4a2e3f31ddc2adb52ebd3204ea6f650d89caf3f - + https://github.com/nuget/nuget.client - c4b26195ee5a77e70b2ea5fd50db87d6a9194c24 + a4a2e3f31ddc2adb52ebd3204ea6f650d89caf3f - + https://github.com/nuget/nuget.client - c4b26195ee5a77e70b2ea5fd50db87d6a9194c24 + a4a2e3f31ddc2adb52ebd3204ea6f650d89caf3f - + https://github.com/nuget/nuget.client - c4b26195ee5a77e70b2ea5fd50db87d6a9194c24 + a4a2e3f31ddc2adb52ebd3204ea6f650d89caf3f - + https://github.com/nuget/nuget.client - c4b26195ee5a77e70b2ea5fd50db87d6a9194c24 + a4a2e3f31ddc2adb52ebd3204ea6f650d89caf3f - + https://github.com/nuget/nuget.client - c4b26195ee5a77e70b2ea5fd50db87d6a9194c24 + a4a2e3f31ddc2adb52ebd3204ea6f650d89caf3f - + https://github.com/nuget/nuget.client - c4b26195ee5a77e70b2ea5fd50db87d6a9194c24 + a4a2e3f31ddc2adb52ebd3204ea6f650d89caf3f - + https://github.com/nuget/nuget.client - c4b26195ee5a77e70b2ea5fd50db87d6a9194c24 + a4a2e3f31ddc2adb52ebd3204ea6f650d89caf3f - + https://github.com/nuget/nuget.client - c4b26195ee5a77e70b2ea5fd50db87d6a9194c24 + a4a2e3f31ddc2adb52ebd3204ea6f650d89caf3f - + https://github.com/nuget/nuget.client - c4b26195ee5a77e70b2ea5fd50db87d6a9194c24 + a4a2e3f31ddc2adb52ebd3204ea6f650d89caf3f - + https://github.com/nuget/nuget.client - c4b26195ee5a77e70b2ea5fd50db87d6a9194c24 + a4a2e3f31ddc2adb52ebd3204ea6f650d89caf3f - + https://github.com/nuget/nuget.client - c4b26195ee5a77e70b2ea5fd50db87d6a9194c24 + a4a2e3f31ddc2adb52ebd3204ea6f650d89caf3f - + https://github.com/nuget/nuget.client - c4b26195ee5a77e70b2ea5fd50db87d6a9194c24 + a4a2e3f31ddc2adb52ebd3204ea6f650d89caf3f - + https://github.com/microsoft/vstest - bcef12d909709f13027afe1557c724f11bc8df05 + 0c76159090e0921b9cf38b95092dbccd4e59cd24 - + https://github.com/microsoft/vstest - bcef12d909709f13027afe1557c724f11bc8df05 + 0c76159090e0921b9cf38b95092dbccd4e59cd24 - + https://github.com/microsoft/vstest - bcef12d909709f13027afe1557c724f11bc8df05 + 0c76159090e0921b9cf38b95092dbccd4e59cd24 - + https://github.com/microsoft/vstest - bcef12d909709f13027afe1557c724f11bc8df05 + 0c76159090e0921b9cf38b95092dbccd4e59cd24 - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/windowsdesktop - 2077f17807081da3fbc2cc4afc9289d29f43d8e2 + 4a45754d6da44a8d1f945b67126f44a55bdc32a6 - + https://github.com/dotnet/windowsdesktop - 2077f17807081da3fbc2cc4afc9289d29f43d8e2 + 4a45754d6da44a8d1f945b67126f44a55bdc32a6 - + https://github.com/dotnet/windowsdesktop - 2077f17807081da3fbc2cc4afc9289d29f43d8e2 + 4a45754d6da44a8d1f945b67126f44a55bdc32a6 - + https://github.com/dotnet/windowsdesktop - 2077f17807081da3fbc2cc4afc9289d29f43d8e2 + 4a45754d6da44a8d1f945b67126f44a55bdc32a6 - + https://github.com/dotnet/wpf - 3ce8132a0e8d6c8a9078d52383d6852b93c981c3 + 6110f47e04816b7064861ad8b4ebae29149aec2b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/razor - 46efcec83821d7f0322c01bc9549de83e855dcac + 25c7bf034222c9621fcc78e6cb503664e4604f0b - + https://github.com/dotnet/razor - 46efcec83821d7f0322c01bc9549de83e855dcac + 25c7bf034222c9621fcc78e6cb503664e4604f0b - + https://github.com/dotnet/razor - 46efcec83821d7f0322c01bc9549de83e855dcac + 25c7bf034222c9621fcc78e6cb503664e4604f0b - + https://github.com/dotnet/razor - 46efcec83821d7f0322c01bc9549de83e855dcac + 25c7bf034222c9621fcc78e6cb503664e4604f0b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/winforms - f0026e791faecab516dc9bd3d16872cd75cdbdb8 + f79026644d3f38a7ab9cfb734a011d5448346d66 - + https://github.com/dotnet/wpf - 3ce8132a0e8d6c8a9078d52383d6852b93c981c3 + 6110f47e04816b7064861ad8b4ebae29149aec2b https://github.com/dotnet/xdt @@ -419,228 +423,228 @@ 1156b9aac00609107c21cf3458b797c76db6be7a - + https://github.com/dotnet/roslyn-analyzers - 45caa455b34553e7ef3ff7cb1def454eef78037c + 8fe7aeb135c64e095f43292c427453858d937184 - + https://github.com/dotnet/roslyn-analyzers - 45caa455b34553e7ef3ff7cb1def454eef78037c + 8fe7aeb135c64e095f43292c427453858d937184 - + https://github.com/dotnet/roslyn-analyzers - 45caa455b34553e7ef3ff7cb1def454eef78037c + 8fe7aeb135c64e095f43292c427453858d937184 - + https://github.com/dotnet/command-line-api - feb61c7f328a2401d74f4317b39d02126cfdfe24 + 3bbb940ceeb3254790899d751a8d418348563d40 - + https://github.com/dotnet/command-line-api - feb61c7f328a2401d74f4317b39d02126cfdfe24 + 3bbb940ceeb3254790899d751a8d418348563d40 - + https://github.com/dotnet/symreader ff1852196a042a124267a6e599d12da20d7ff65a - + https://github.com/dotnet/command-line-api - feb61c7f328a2401d74f4317b39d02126cfdfe24 + 3bbb940ceeb3254790899d751a8d418348563d40 - + https://github.com/dotnet/source-build-externals - c9e4423c80e00371e43e306ee6e2e97fd2196af9 + 962bb86f95ebece01c2b1de97ed7d4261e00b058 - + https://github.com/dotnet/source-build-reference-packages - be366997dfae0aa6e3c9a78bad10bfb3f79cbde1 + f18184030957ae8b02c6cb971ff2a58a06d2e7b1 - + https://github.com/dotnet/deployment-tools - c7bcd7d32f7744af89dfd031a9b2085e3004fd9c + eddd72e696074a457cabf62df5d889928324e0b7 - + https://github.com/dotnet/sourcelink - 762b0e8b055fe9f203755b651e67c829e759f44d + fab841741055c19fc07623f8947cecc9a0f63baa - + https://github.com/dotnet/sourcelink - 762b0e8b055fe9f203755b651e67c829e759f44d + fab841741055c19fc07623f8947cecc9a0f63baa - + https://github.com/dotnet/sourcelink - 762b0e8b055fe9f203755b651e67c829e759f44d + fab841741055c19fc07623f8947cecc9a0f63baa - + https://github.com/dotnet/sourcelink - 762b0e8b055fe9f203755b651e67c829e759f44d + fab841741055c19fc07623f8947cecc9a0f63baa - + https://github.com/dotnet/sourcelink - 762b0e8b055fe9f203755b651e67c829e759f44d + fab841741055c19fc07623f8947cecc9a0f63baa - + https://github.com/dotnet/sourcelink - 762b0e8b055fe9f203755b651e67c829e759f44d + fab841741055c19fc07623f8947cecc9a0f63baa - + https://github.com/dotnet/sourcelink - 762b0e8b055fe9f203755b651e67c829e759f44d + fab841741055c19fc07623f8947cecc9a0f63baa - + https://github.com/dotnet/deployment-tools - c7bcd7d32f7744af89dfd031a9b2085e3004fd9c + eddd72e696074a457cabf62df5d889928324e0b7 - + https://github.com/dotnet/symreader ff1852196a042a124267a6e599d12da20d7ff65a - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/aspnetcore - 82269fc71f9ebb38457d5a0010a1171430f16db5 + febd7e8bdf05f17fb4e0e4dd3123e9538fbf7e7b - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/arcade - 98b4ae348fa01b99dc6fbfc8f601efd9b90090db + bbea86c614fcf4380c58c80eacd279a0b8305a79 - + https://github.com/dotnet/arcade - 98b4ae348fa01b99dc6fbfc8f601efd9b90090db + bbea86c614fcf4380c58c80eacd279a0b8305a79 - + https://github.com/dotnet/arcade - 98b4ae348fa01b99dc6fbfc8f601efd9b90090db + bbea86c614fcf4380c58c80eacd279a0b8305a79 - + https://github.com/dotnet/arcade - 98b4ae348fa01b99dc6fbfc8f601efd9b90090db + bbea86c614fcf4380c58c80eacd279a0b8305a79 - + https://github.com/dotnet/arcade - 98b4ae348fa01b99dc6fbfc8f601efd9b90090db + bbea86c614fcf4380c58c80eacd279a0b8305a79 - + https://github.com/dotnet/arcade - 98b4ae348fa01b99dc6fbfc8f601efd9b90090db + bbea86c614fcf4380c58c80eacd279a0b8305a79 - + https://github.com/dotnet/arcade - 98b4ae348fa01b99dc6fbfc8f601efd9b90090db + bbea86c614fcf4380c58c80eacd279a0b8305a79 - + https://github.com/dotnet/runtime - 6c58f7992cfd628a53d9b90f258ac123cb803644 + e51af404d1ea26be4a3d8e51fe21cf2f09ad34dd - + https://github.com/dotnet/arcade-services - 6c7cc1d1653051d35db84d40ef77ee6702d91436 + 0a9f6b177026a7473b9225355269c2c9a90b777f - + https://github.com/dotnet/arcade-services - 6c7cc1d1653051d35db84d40ef77ee6702d91436 + 0a9f6b177026a7473b9225355269c2c9a90b777f https://github.com/dotnet/scenario-tests @@ -675,13 +679,13 @@ https://github.com/dotnet/runtime e77011b31a3e5c47d931248a64b47f9b2d47853d - + https://github.com/microsoft/testfx - edc05edf02f74ff5d32b02c782bf10aa1d774a5b + b5c93525849bce7009877e042501e171edc9585a - + https://github.com/microsoft/testfx - edc05edf02f74ff5d32b02c782bf10aa1d774a5b + b5c93525849bce7009877e042501e171edc9585a diff --git a/eng/Versions.props b/eng/Versions.props index 7904d6b34c41..ad5f94af7360 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -18,17 +18,18 @@ false release - alpha + preview rtm servicing - 1 + 2 true 6.0.1 true - 1.6.0-preview.25067.5 + + 1.6.0-preview.25101.5 30 @@ -36,8 +37,8 @@ 17 36 20 - 11 - 0 + 12 + 1 <_NET70ILLinkPackVersion>7.0.100-1.23211.1 @@ -57,10 +58,9 @@ 4.8.6 1.2.0-beta.435 4.0.5 - 2.0.0-beta4.24528.1 - 0.4.0-alpha.24528.1 - 2.0.0-preview.1.24630.1 - 2.2.0-beta.24622.1 + 2.0.0-beta4.25071.2 + 2.0.0-preview.1.25071.2 + 2.2.0-beta.25076.1 1.1.2-beta1.22216.1 10.3.0 3.2.2146 @@ -75,7 +75,7 @@ - 1.1.0-beta.25064.2 + 1.1.0-beta.25081.2 @@ -83,83 +83,86 @@ - 10.0.0-alpha.1.25066.5 + 10.0.0-preview.2.25080.2 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 8.0.0-rc.1.23414.4 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 2.1.0 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 - 10.0.0-alpha.1.25067.10 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 + 10.0.0-preview.2.25101.4 8.0.0 2.0.0-preview.1.24427.4 + 4.5.1 8.0.0 + 4.5.5 8.0.0 8.0.0 8.0.5 + 4.5.4 8.0.0 - 10.0.0-alpha.1.25067.6 - 10.0.0-alpha.1.25067.6 - 10.0.0-alpha.1.25067.6 + 10.0.0-preview.2.25081.1 + 10.0.0-preview.2.25081.1 + 10.0.0-preview.2.25081.1 - 6.13.0-rc.113 - 6.13.0-rc.113 - 6.13.0-rc.113 - 6.13.0-rc.113 - 6.13.0-rc.113 - 6.13.0-rc.113 - 6.13.0-rc.113 - 6.13.0-rc.113 - 6.13.0-rc.113 - 6.13.0-rc.113 - 6.13.0-rc.113 - 6.13.0-rc.113 + 6.14.0-preview.1.11 + 6.14.0-preview.1.11 + 6.14.0-preview.1.11 + 6.14.0-preview.1.11 + 6.14.0-preview.1.11 + 6.14.0-preview.1.11 + 6.14.0-preview.1.11 + 6.14.0-preview.1.11 + 6.14.0-preview.1.11 + 6.14.0-preview.1.11 + 6.14.0-preview.1.11 + 6.14.0-preview.1.11 - 17.13.0-preview-25060-03 - 17.13.0-preview-25060-03 - 17.13.0-preview-25060-03 + 17.14.0-preview-25079-01 + 17.14.0-preview-25079-01 + 17.14.0-preview-25079-01 @@ -167,8 +170,8 @@ - 10.0.0-preview.25066.1 - 3.12.0-beta1.25066.1 + 10.0.0-preview.25081.1 + 3.12.0-beta1.25081.1 @@ -189,65 +192,66 @@ At usage sites, either we use MicrosoftBuildMinimumVersion, or MicrosoftBuildVersion in source-only modes. Additionally, set the MinimumVSVersion for the installer UI that's required for targeting NetCurrent --> - 17.14.0-preview-25067-08 - 17.14.0-preview-25067-08 + 17.14.0-preview-25073-02 + 17.14.0-preview-25073-02 17.11.4 17.12 - 10.0.100-alpha.1.25066.10 + 10.0.100-preview.2.25080.1 $(MicrosoftTemplateEngineAbstractionsPackageVersion) $(MicrosoftTemplateEngineAbstractionsPackageVersion) $(MicrosoftTemplateEngineAbstractionsPackageVersion) $(MicrosoftTemplateEngineAbstractionsPackageVersion) - 10.0.100-alpha.1.25066.10 + 10.0.100-preview.2.25080.1 $(MicrosoftTemplateEngineMocksPackageVersion) $(MicrosoftTemplateEngineAbstractionsPackageVersion) $(MicrosoftTemplateEngineMocksPackageVersion) - 13.9.300-beta.25067.2 + 13.9.300-beta.25079.4 - 4.14.0-1.25068.1 - 4.14.0-1.25068.1 - 4.14.0-1.25068.1 - 4.14.0-1.25068.1 - 4.14.0-1.25068.1 - 4.14.0-1.25068.1 - 4.14.0-1.25068.1 - 4.14.0-1.25068.1 + 4.14.0-1.25070.2 + 4.14.0-1.25070.2 + 4.14.0-1.25070.2 + 4.14.0-1.25070.2 + 4.14.0-1.25070.2 + 4.14.0-1.25070.2 + 4.14.0-1.25070.2 + 4.14.0-1.25070.2 + 4.14.0-1.25070.2 - 10.0.0-alpha.2.25068.1 - 10.0.0-alpha.2.25068.1 - 10.0.0-alpha.2.25068.1 - 10.0.0-alpha.2.25068.1 - 10.0.0-alpha.2.25068.1 - 10.0.0-alpha.2.25068.1 - 10.0.0-alpha.2.25068.1 - 10.0.0-alpha.2.25068.1 - 10.0.0-alpha.2.25068.1 - 10.0.0-alpha.2.25068.1 - 10.0.0-alpha.2.25068.1 - 10.0.0-alpha.2.25068.1 - 10.0.0-alpha.2.25068.1 + 10.0.0-alpha.2.25073.4 + 10.0.0-alpha.2.25073.4 + 10.0.0-alpha.2.25073.4 + 10.0.0-alpha.2.25073.4 + 10.0.0-alpha.2.25073.4 + 10.0.0-alpha.2.25073.4 + 10.0.0-alpha.2.25073.4 + 10.0.0-alpha.2.25073.4 + 10.0.0-alpha.2.25073.4 + 10.0.0-alpha.2.25073.4 + 10.0.0-alpha.2.25073.4 + 10.0.0-alpha.2.25073.4 + 10.0.0-alpha.2.25073.4 - 9.0.0-preview.25058.6 - 9.0.0-preview.25058.6 - 9.0.0-preview.25058.6 + 9.0.0-preview.25081.4 + 9.0.0-preview.25081.4 + 9.0.0-preview.25081.4 - 10.0.0-alpha.1.25067.3 - 10.0.0-alpha.1.25067.3 + 10.0.0-preview.2.25081.3 + 10.0.0-preview.2.25081.3 @@ -266,19 +270,19 @@ - 10.0.0-beta.25061.1 - 10.0.0-beta.25061.1 - 10.0.0-beta.25061.1 - 10.0.0-beta.25061.1 + 10.0.0-beta.25080.7 + 10.0.0-beta.25080.7 + 10.0.0-beta.25080.7 + 10.0.0-beta.25080.7 - 9.0.0-beta.25066.1 - 9.0.0-beta.25066.1 - 9.0.0-beta.25066.1 - 9.0.0-beta.25066.1 - 9.0.0-beta.25066.1 - 9.0.0-beta.25066.1 + 10.0.0-beta.25080.2 + 10.0.0-beta.25080.2 + 10.0.0-beta.25080.2 + 10.0.0-beta.25080.2 + 10.0.0-beta.25080.2 + 10.0.0-beta.25080.2 @@ -289,7 +293,7 @@ 6.12.0 6.1.0 4.18.4 - 3.8.0-preview.25067.5 + 3.8.0-preview.25101.5 1.3.2 8.0.0-beta.23607.1 diff --git a/eng/common/internal/Tools.csproj b/eng/common/internal/Tools.csproj index 32f79dfb3402..feaa6d20812d 100644 --- a/eng/common/internal/Tools.csproj +++ b/eng/common/internal/Tools.csproj @@ -15,16 +15,6 @@ - - - - https://devdiv.pkgs.visualstudio.com/_packaging/dotnet-core-internal-tooling/nuget/v3/index.json; - - - $(RestoreSources); - https://devdiv.pkgs.visualstudio.com/_packaging/VS/nuget/v3/index.json; - - diff --git a/eng/common/native/install-dependencies.sh b/eng/common/native/install-dependencies.sh index 71bde0e4573b..ce661e9e5cd8 100755 --- a/eng/common/native/install-dependencies.sh +++ b/eng/common/native/install-dependencies.sh @@ -24,13 +24,13 @@ case "$os" in apt update apt install -y build-essential gettext locales cmake llvm clang lld lldb liblldb-dev libunwind8-dev libicu-dev liblttng-ust-dev \ - libssl-dev libkrb5-dev zlib1g-dev pigz cpio + libssl-dev libkrb5-dev pigz cpio localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 elif [ "$ID" = "fedora" ] || [ "$ID" = "rhel" ]; then - dnf install -y cmake llvm lld lldb clang python curl libicu-devel openssl-devel krb5-devel zlib-devel lttng-ust-devel pigz cpio + dnf install -y cmake llvm lld lldb clang python curl libicu-devel openssl-devel krb5-devel lttng-ust-devel pigz cpio elif [ "$ID" = "alpine" ]; then - apk add build-base cmake bash curl clang llvm-dev lld lldb krb5-dev lttng-ust-dev icu-dev zlib-dev openssl-dev pigz cpio + apk add build-base cmake bash curl clang llvm-dev lld lldb krb5-dev lttng-ust-dev icu-dev openssl-dev pigz cpio else echo "Unsupported distro. distro: $ID" exit 1 diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 853c63849626..80f9130b1508 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -42,7 +42,7 @@ [bool]$useInstalledDotNetCli = if (Test-Path variable:useInstalledDotNetCli) { $useInstalledDotNetCli } else { $true } # Enable repos to use a particular version of the on-line dotnet-install scripts. -# default URL: https://dotnet.microsoft.com/download/dotnet/scripts/v1/dotnet-install.ps1 +# default URL: https://builds.dotnet.microsoft.com/dotnet/scripts/v1/dotnet-install.ps1 [string]$dotnetInstallScriptVersion = if (Test-Path variable:dotnetInstallScriptVersion) { $dotnetInstallScriptVersion } else { 'v1' } # True to use global NuGet cache instead of restoring packages to repository-local directory. @@ -262,7 +262,7 @@ function GetDotNetInstallScript([string] $dotnetRoot) { if (!(Test-Path $installScript)) { Create-Directory $dotnetRoot $ProgressPreference = 'SilentlyContinue' # Don't display the console progress UI - it's a huge perf hit - $uri = "https://raw.githubusercontent.com/dotnet/install-scripts/4b17227b30fbbad567d4d4fba17c59da51bc817b/src/dotnet-install.ps1" + $uri = "https://builds.dotnet.microsoft.com/dotnet/scripts/v1/dotnet-install.ps1" Retry({ Write-Host "GET $uri" diff --git a/eng/common/tools.sh b/eng/common/tools.sh index 84ab5f124acc..df203b517842 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -54,7 +54,7 @@ warn_as_error=${warn_as_error:-true} use_installed_dotnet_cli=${use_installed_dotnet_cli:-true} # Enable repos to use a particular version of the on-line dotnet-install scripts. -# default URL: https://dotnet.microsoft.com/download/dotnet/scripts/v1/dotnet-install.sh +# default URL: https://builds.dotnet.microsoft.com/dotnet/scripts/v1/dotnet-install.sh dotnetInstallScriptVersion=${dotnetInstallScriptVersion:-'v1'} # True to use global NuGet cache instead of restoring packages to repository-local directory. @@ -295,7 +295,7 @@ function with_retries { function GetDotNetInstallScript { local root=$1 local install_script="$root/dotnet-install.sh" - local install_script_url="https://raw.githubusercontent.com/dotnet/install-scripts/4b17227b30fbbad567d4d4fba17c59da51bc817b/src/dotnet-install.sh" + local install_script_url="https://builds.dotnet.microsoft.com/dotnet/scripts/v1/dotnet-install.sh" if [[ ! -a "$install_script" ]]; then mkdir -p "$root" diff --git a/eng/install-scancode.sh b/eng/install-scancode.sh index c82c274ed018..39ad70be318c 100755 --- a/eng/install-scancode.sh +++ b/eng/install-scancode.sh @@ -5,7 +5,7 @@ set -euo pipefail # Install instructions: https://scancode-toolkit.readthedocs.io/en/latest/getting-started/install.html#installation-as-a-library-via-pip # See latest release at https://github.com/nexB/scancode-toolkit/releases -SCANCODE_VERSION="32.2.1" +SCANCODE_VERSION="32.3.2" pyEnvPath="/tmp/scancode-env" python3 -m venv $pyEnvPath diff --git a/eng/pipelines/templates/jobs/vmr-build.yml b/eng/pipelines/templates/jobs/vmr-build.yml index a85476f6dc5d..9c570993ed5d 100644 --- a/eng/pipelines/templates/jobs/vmr-build.yml +++ b/eng/pipelines/templates/jobs/vmr-build.yml @@ -43,13 +43,8 @@ parameters: type: boolean default: false -- name: useDevVersions - displayName: True when build output uses dev/CI versioning instead of official build versioning - type: boolean - default: false - - name: sign - displayName: True when build output should be signed + displayName: True when build output should be signed (includes dry runs) type: boolean default: true @@ -142,9 +137,13 @@ jobs: ${{ if ne(parameters.reuseBuildArtifactsFrom, '') }}: ${{ if eq(parameters.buildPass, '') }}: - # Always attempt to run the bootstrap leg (e.g. even when stage 1 tests fail) in order to get a complete accessment of the build status. + # For PR builds, skip the stage 2 build if the stage 1 build fails. + # Otherwise, run the stage 2 build even if the stage 1 build fails so that we can get a complete assessment of the build status. # The build shortcuts when stage 1 build fails and doesn't produce the SDK. - condition: succeededOrFailed() + ${{ if eq(variables['Build.Reason'], 'PullRequest') }}: + condition: succeeded() + ${{ else }}: + condition: succeededOrFailed() ${{ else }}: condition: succeeded() dependsOn: ${{ parameters.reuseBuildArtifactsFrom }} @@ -199,25 +198,14 @@ jobs: - ${{ if eq(parameters.targetOS, 'windows') }}: ## Basic arguments - name: baseArguments - value: -ci -cleanWhileBuilding -prepareMachine /p:VerticalName=$(Agent.JobName) /p:ArtifactsStagingDir=$(artifactsStagingDir) - - - name: configArguments - value: -c ${{ parameters.configuration }} + value: -ci -cleanWhileBuilding -prepareMachine -c ${{ parameters.configuration }} $(officialBuildParameter) /p:VerticalName=$(Agent.JobName) /p:ArtifactsStagingDir=$(artifactsStagingDir) - name: targetArguments value: /p:TargetOS=${{ parameters.targetOS }} /p:TargetArchitecture=${{ parameters.targetArchitecture }} - ### Dev versions variables - - ${{ if eq(parameters.useDevVersions, 'True') }}: - - name: devArguments - value: -dev - - ${{ else }}: - - name: devArguments - value: '' - ### Signing variables - ${{ if eq(parameters.sign, 'True') }}: - - ${{ if or(eq(parameters.useDevVersions, 'True'), eq(variables['System.TeamProject'], 'public'), in(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if or(eq(variables['System.TeamProject'], 'public'), in(variables['Build.Reason'], 'PullRequest')) }}: # The _SignType variable is used by microbuild installation - name: _SignType value: '' @@ -375,9 +363,7 @@ jobs: - script: build.cmd $(baseArguments) - $(configArguments) $(targetArguments) - $(devArguments) $(signArguments) $(buildPassArguments) ${{ parameters.extraProperties }} @@ -385,8 +371,14 @@ jobs: workingDirectory: ${{ variables.sourcesPath }} - ${{ if eq(parameters.runTests, 'True') }}: - - script: | - call build.cmd -ci -prepareMachine -test -excludeCIBinarylog /bl:artifacts/log/Release/Test.binlog -c ${{ parameters.configuration }} /p:TargetOS=${{ parameters.targetOS }} /p:TargetArchitecture=${{ parameters.targetArchitecture }} /p:VerticalName=$(Agent.JobName) /p:ArtifactsStagingDir=$(artifactsStagingDir) ${{ parameters.extraProperties }} + - script: build.cmd + $(baseArguments) + $(targetArguments) + $(buildPassArguments) + ${{ parameters.extraProperties }} + -test + -excludeCIBinarylog + /bl:artifacts/log/Release/Test.binlog displayName: Run Tests workingDirectory: ${{ variables.sourcesPath }} timeoutInMinutes: ${{ variables.runTestsTimeout }} @@ -436,7 +428,7 @@ jobs: customEnvVars="" customPreBuildArgs="" - customBuildArgs="--ci --clean-while-building --prepareMachine -c ${{ parameters.configuration }}" + customBuildArgs="--ci --clean-while-building --prepareMachine -c ${{ parameters.configuration }} $(officialBuildParameter)" if [[ '${{ parameters.runOnline }}' == 'True' ]]; then customBuildArgs="$customBuildArgs --online" @@ -462,10 +454,6 @@ jobs: customBuildArgs="$customBuildArgs --use-mono-runtime" fi - if [[ '${{ parameters.useDevVersions }}' == 'True' ]]; then - customBuildArgs="$customBuildArgs --dev" - fi - if [[ '${{ parameters.sign }}' == 'True' ]] && [[ '${{ parameters.buildSourceOnly }}' != 'True' ]]; then customBuildArgs="$customBuildArgs --sign" if [[ '$(_SignType)' == 'real' ]] || [[ '$(_SignType)' == 'test' ]]; then @@ -546,7 +534,7 @@ jobs: customPreBuildArgs='' customBuildArgs='' extraBuildProperties='' - customBuildArgs="--ci --prepareMachine -c ${{ parameters.configuration }}" + customBuildArgs="--ci --prepareMachine -c ${{ parameters.configuration }} $(officialBuildParameter)" if [[ '${{ parameters.runOnline }}' == 'False' ]]; then customPreBuildArgs="$customPreBuildArgs sudo" @@ -560,10 +548,6 @@ jobs: extraBuildProperties="$extraBuildProperties /p:TargetArchitecture=${{ parameters.targetArchitecture }}" fi - if [[ '${{ parameters.useDevVersions }}' == 'True' ]]; then - customBuildArgs="$customBuildArgs --dev" - fi - if [[ '${{ parameters.buildSourceOnly }}' == 'True' ]]; then if [[ '${{ parameters.enablePoison }}' == 'True' ]]; then customBuildArgs="$customBuildArgs --poison" @@ -600,7 +584,6 @@ jobs: SourceFolder: '$(sourcesPath)' Contents: | artifacts/log/** - artifacts/scenario-tests/**/*.binlog artifacts/TestResults/**/*.binlog artifacts/TestResults/**/*.diff artifacts/TestResults/**/Updated*.txt diff --git a/eng/pipelines/templates/stages/vmr-build.yml b/eng/pipelines/templates/stages/vmr-build.yml index bdede627acf5..59821af97fb5 100644 --- a/eng/pipelines/templates/stages/vmr-build.yml +++ b/eng/pipelines/templates/stages/vmr-build.yml @@ -7,6 +7,10 @@ parameters: type: string default: $(Build.SourceBranch) +- name: desiredSigning + type: string + default: '' + # Scope of jobs which are executed - name: scope type: string @@ -369,19 +373,6 @@ stages: image: ${{ variables.ubuntuContainerImage }} targetOS: linux targetArchitecture: x64 - useDevVersions: true # Use dev versions for CI validation of the experience. - runTests: false # Temporarily do not run tests. The nuget comparison fails for some non-obvious reason and needs further investigation. Mostly, I'm not sure why it ever passed. https://github.com/dotnet/sdk/issues/42920 - - - template: ../jobs/vmr-build.yml - parameters: - buildName: Windows_DevVersions - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Windows }} - targetOS: windows - targetArchitecture: x64 - useDevVersions: true # Use dev versions for CI validation of the experience. - runTests: false # Temporarily do not run tests. The nuget comparison fails for some non-obvious reason and needs further investigation. Mostly, I'm not sure why it ever passed. https://github.com/dotnet/sdk/issues/42920 #### VERTICAL BUILD (Official) #### - ${{ if not(parameters.isSourceOnlyBuild) }}: @@ -392,6 +383,7 @@ stages: - template: ../variables/vmr-build.yml parameters: vmrBranch: ${{ parameters.vmrBranch }} + desiredSigning: ${{ parameters.desiredSigning }} jobs: - template: ../jobs/vmr-build.yml @@ -399,28 +391,40 @@ stages: buildName: Windows isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Windows }} targetOS: windows targetArchitecture: x64 + - template: ../jobs/vmr-build.yml + parameters: + buildName: Windows + isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} + vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} + pool: ${{ parameters.pool_Windows }} + targetOS: windows + targetArchitecture: x86 + - template: ../jobs/vmr-build.yml parameters: buildName: Android_Shortstack isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Linux_Shortstack }} container: name: ${{ variables.androidCrossContainerName }} image: ${{ variables.androidCrossContainerImage }} targetOS: android targetArchitecture: arm64 - runTests: false - template: ../jobs/vmr-build.yml parameters: buildName: Browser_Shortstack isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Linux_Shortstack }} container: name: ${{ variables.browserCrossContainerName }} @@ -428,17 +432,16 @@ stages: crossRootFs: '/crossrootfs/x64' targetOS: browser targetArchitecture: wasm - runTests: false - template: ../jobs/vmr-build.yml parameters: buildName: iOSSimulator_Shortstack isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Mac }} targetOS: iossimulator targetArchitecture: arm64 - runTests: false ### Additional jobs for full build ### - ${{ if in(parameters.scope, 'full') }}: @@ -448,45 +451,46 @@ stages: buildName: Android_Shortstack isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Linux_Shortstack }} container: name: ${{ variables.androidCrossContainerName }} image: ${{ variables.androidCrossContainerImage }} targetOS: android targetArchitecture: arm - runTests: false - template: ../jobs/vmr-build.yml parameters: buildName: Android_Shortstack isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Linux_Shortstack }} container: name: ${{ variables.androidCrossContainerName }} image: ${{ variables.androidCrossContainerImage }} targetOS: android targetArchitecture: x64 - runTests: false - template: ../jobs/vmr-build.yml parameters: buildName: Android_Shortstack isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Linux_Shortstack }} container: name: ${{ variables.androidCrossContainerName }} image: ${{ variables.androidCrossContainerImage }} targetOS: android targetArchitecture: x86 - runTests: false - template: ../jobs/vmr-build.yml parameters: buildName: Browser_Multithreaded_Shortstack isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Linux_Shortstack }} container: name: ${{ variables.browserCrossContainerName }} @@ -495,13 +499,13 @@ stages: targetOS: browser targetArchitecture: wasm extraProperties: /p:DotNetBuildRuntimeWasmEnableThreads=true - runTests: false - template: ../jobs/vmr-build.yml parameters: buildName: LinuxBionic_Shortstack isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Linux_Shortstack }} container: name: ${{ variables.linuxBionicCrossContainerName }} @@ -509,28 +513,13 @@ stages: crossRootFs: '/crossrootfs/x64' targetOS: linux-bionic targetArchitecture: arm64 - runTests: false - template: ../jobs/vmr-build.yml parameters: - buildName: LinuxBionic_NativeAOT_Shortstack - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Linux_Shortstack }} - container: - name: ${{ variables.linuxBionicCrossContainerName }} - image: ${{ variables.linuxBionicCrossContainerImage }} - crossRootFs: '/crossrootfs/x64' - targetOS: linux-bionic - targetArchitecture: arm64 - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: LinuxBionic_NativeAOT_Shortstack + buildName: LinuxBionic_Shortstack isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Linux_Shortstack }} container: name: ${{ variables.linuxBionicCrossContainerName }} @@ -538,14 +527,13 @@ stages: crossRootFs: '/crossrootfs/x64' targetOS: linux-bionic targetArchitecture: arm - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - template: ../jobs/vmr-build.yml parameters: buildName: LinuxBionic_Shortstack isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Linux_Shortstack }} container: name: ${{ variables.linuxBionicCrossContainerName }} @@ -553,186 +541,83 @@ stages: crossRootFs: '/crossrootfs/x64' targetOS: linux-bionic targetArchitecture: x64 - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: LinuxBionic_NativeAOT_Shortstack - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Linux_Shortstack }} - container: - name: ${{ variables.linuxBionicCrossContainerName }} - image: ${{ variables.linuxBionicCrossContainerImage }} - crossRootFs: '/crossrootfs/x64' - targetOS: linux-bionic - targetArchitecture: x64 - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - template: ../jobs/vmr-build.yml parameters: buildName: iOS_Shortstack isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Mac }} targetOS: ios targetArchitecture: arm64 - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: iOS_NativeAOT_Shortstack - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Mac }} - targetOS: ios - targetArchitecture: arm64 - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: iOSSimulator_NativeAOT_Shortstack - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Mac }} - targetOS: iossimulator - targetArchitecture: arm64 - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - template: ../jobs/vmr-build.yml parameters: buildName: iOSSimulator_Shortstack isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Mac }} targetOS: iossimulator targetArchitecture: x64 - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: iOSSimulator_NativeAOT_Shortstack - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Mac }} - targetOS: iossimulator - targetArchitecture: x64 - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - template: ../jobs/vmr-build.yml parameters: buildName: MacCatalyst_Shortstack isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Mac }} targetOS: maccatalyst targetArchitecture: arm64 - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: MacCatalyst_NativeAOT_Shortstack - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Mac }} - targetOS: maccatalyst - targetArchitecture: arm64 - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - template: ../jobs/vmr-build.yml parameters: buildName: MacCatalyst_Shortstack isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Mac }} targetOS: maccatalyst targetArchitecture: x64 - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: MacCatalyst_NativeAOT_Shortstack - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Mac }} - targetOS: maccatalyst - targetArchitecture: x64 - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - template: ../jobs/vmr-build.yml parameters: buildName: tvOS_Shortstack isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Mac }} targetOS: tvos targetArchitecture: arm64 - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: tvOS_NativeAOT_Shortstack - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Mac }} - targetOS: tvos - targetArchitecture: arm64 - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - template: ../jobs/vmr-build.yml parameters: buildName: tvOSSimulator_Shortstack isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Mac }} targetOS: tvossimulator targetArchitecture: arm64 - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: tvOSSimulator_NativeAOT_Shortstack - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Mac }} - targetOS: tvossimulator - targetArchitecture: arm64 - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - template: ../jobs/vmr-build.yml parameters: buildName: tvOSSimulator_Shortstack isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Mac }} targetOS: tvossimulator targetArchitecture: x64 - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: tvOSSimulator_NativeAOT_Shortstack - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Mac }} - targetOS: tvossimulator - targetArchitecture: x64 - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - template: ../jobs/vmr-build.yml parameters: buildName: Wasi_Shortstack isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Linux_Shortstack }} container: name: ${{ variables.wasiCrossContainerName }} @@ -740,32 +625,23 @@ stages: crossRootFs: '/crossrootfs/x64' targetOS: wasi targetArchitecture: wasm - runTests: false - template: ../jobs/vmr-build.yml parameters: buildName: OSX isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Mac }} targetOS: osx targetArchitecture: x64 - - template: ../jobs/vmr-build.yml - parameters: - buildName: OSX_Mono - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Mac }} - useMonoRuntime: true - targetOS: osx - targetArchitecture: x64 - - template: ../jobs/vmr-build.yml parameters: buildName: AzureLinux_x64_Cross isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Linux }} container: name: ${{ variables.azurelinuxX64CrossContainerName }} @@ -779,37 +655,22 @@ stages: buildName: AzureLinux_x64_Cross_Pgo isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Linux }} - container: - name: ${{ variables.azurelinuxX64CrossContainerName }} - image: ${{ variables.azurelinuxX64CrossContainerImage }} - crossRootFs: '/crossrootfs/x64' - targetOS: linux - targetArchitecture: x64 - extraProperties: /p:PgoInstrument=true - runTests: false sign: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: AzureLinux_x64_Cross_Mono - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} pool: ${{ parameters.pool_Linux }} container: name: ${{ variables.azurelinuxX64CrossContainerName }} image: ${{ variables.azurelinuxX64CrossContainerImage }} crossRootFs: '/crossrootfs/x64' - useMonoRuntime: true targetOS: linux targetArchitecture: x64 - runTests: false # scenario-tests time out: https://github.com/dotnet/source-build/issues/4775 + extraProperties: /p:PgoInstrument=true - template: ../jobs/vmr-build.yml parameters: - buildName: AzureLinux_x64_Cross_ShortStack_Mono_LLVMAOT + buildName: AzureLinux_x64_Cross_Shortstack_Mono_LLVMAOT isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Linux_Shortstack }} container: name: ${{ variables.azurelinuxX64CrossContainerName }} @@ -819,13 +680,13 @@ stages: targetOS: linux targetArchitecture: x64 extraProperties: /p:DotNetBuildMonoEnableLLVM=true /p:DotNetBuildMonoAOTEnableLLVM=true /p:DotNetBuildMonoBundleLLVMOptimizer=true - runTests: false - template: ../jobs/vmr-build.yml parameters: buildName: AzureLinux_x64_Cross isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Linux }} container: name: ${{ variables.azurelinuxArmCrossContainerName }} @@ -834,40 +695,12 @@ stages: targetOS: linux targetArchitecture: arm - - template: ../jobs/vmr-build.yml - parameters: - buildName: AzureLinux_x64_Cross_Mono - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Linux }} - container: - name: ${{ variables.azurelinuxArmCrossContainerName }} - image: ${{ variables.azurelinuxArmCrossContainerImage }} - crossRootFs: '/crossrootfs/arm' - useMonoRuntime: true - targetOS: linux - targetArchitecture: arm - - - template: ../jobs/vmr-build.yml - parameters: - buildName: AzureLinux_x64_Cross_ShortStack_NativeAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Linux }} - container: - name: ${{ variables.azurelinuxArmCrossContainerName }} - image: ${{ variables.azurelinuxArmCrossContainerImage }} - crossRootFs: '/crossrootfs/arm' - targetOS: linux - targetArchitecture: arm - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - - template: ../jobs/vmr-build.yml parameters: buildName: AzureLinux_x64_Cross isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Linux }} container: name: ${{ variables.azurelinuxArm64CrossContainerName }} @@ -881,56 +714,27 @@ stages: buildName: AzureLinux_x64_Cross_Pgo isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Linux }} - container: - name: ${{ variables.azurelinuxArm64CrossContainerName }} - image: ${{ variables.azurelinuxArm64CrossContainerImage }} - crossRootFs: '/crossrootfs/arm64' - targetOS: linux - targetArchitecture: arm64 - extraProperties: /p:PgoInstrument=true - runTests: false sign: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: AzureLinux_x64_Cross_Mono - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} pool: ${{ parameters.pool_Linux }} container: name: ${{ variables.azurelinuxArm64CrossContainerName }} image: ${{ variables.azurelinuxArm64CrossContainerImage }} crossRootFs: '/crossrootfs/arm64' - useMonoRuntime: true targetOS: linux targetArchitecture: arm64 + extraProperties: /p:PgoInstrument=true - template: ../jobs/vmr-build.yml parameters: buildName: AzureLinux_x64_Cross_Alpine isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Linux }} container: - name: ${{ variables.azurelinuxX64AlpineCrossContainerName }} - image: ${{ variables.azurelinuxX64AlpineCrossContainerImage }} - crossRootFs: '/crossrootfs/x64' - targetOS: linux-musl - targetArchitecture: x64 - targetRid: ${{ variables.linuxMuslX64Rid}} - - - template: ../jobs/vmr-build.yml - parameters: - buildName: AzureLinux_x64_Cross_Alpine_Mono - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Linux }} - container: - name: ${{ variables.azurelinuxX64AlpineCrossContainerName }} - image: ${{ variables.azurelinuxX64AlpineCrossContainerImage }} + name: ${{ variables.azurelinuxX64MuslCrossContainerName }} + image: ${{ variables.azurelinuxX64MuslCrossContainerImage }} crossRootFs: '/crossrootfs/x64' - useMonoRuntime: true targetOS: linux-musl targetArchitecture: x64 targetRid: ${{ variables.linuxMuslX64Rid }} @@ -940,10 +744,11 @@ stages: buildName: AzureLinux_x64_Cross_Alpine isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Linux }} container: - name: ${{ variables.azurelinuxArmAlpineCrossContainerName }} - image: ${{ variables.azurelinuxArmAlpineCrossContainerImage }} + name: ${{ variables.azurelinuxArmMuslCrossContainerName }} + image: ${{ variables.azurelinuxArmMuslCrossContainerImage }} crossRootFs: '/crossrootfs/arm' targetOS: linux-musl targetArchitecture: arm @@ -954,10 +759,11 @@ stages: buildName: AzureLinux_x64_Cross_Alpine isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Linux }} container: - name: ${{ variables.azurelinuxArm64AlpineCrossContainerName }} - image: ${{ variables.azurelinuxArm64AlpineCrossContainerImage }} + name: ${{ variables.azurelinuxArm64MuslCrossContainerName }} + image: ${{ variables.azurelinuxArm64MuslCrossContainerImage }} crossRootFs: '/crossrootfs/arm64' targetOS: linux-musl targetArchitecture: arm64 @@ -965,134 +771,10 @@ stages: - template: ../jobs/vmr-build.yml parameters: - buildName: AzureLinux_x64_Cross_ShortStack_Alpine_Mono_CrossAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Linux }} - container: - name: ${{ variables.azurelinuxX64AlpineCrossContainerName }} - image: ${{ variables.azurelinuxX64AlpineCrossContainerImage }} - crossRootFs: '/crossrootfs/x64' - targetOS: linux-musl - targetArchitecture: x64 - targetRid: ${{ variables.linuxMuslX64Rid }} - extraProperties: /p:DotNetBuildMonoCrossAOT=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: AzureLinux_x64_Cross_ShortStack_Alpine_Mono_CrossAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Linux }} - container: - name: ${{ variables.azurelinuxArm64AlpineCrossContainerName }} - image: ${{ variables.azurelinuxArm64AlpineCrossContainerImage }} - crossRootFs: '/crossrootfs/arm64' - targetOS: linux-musl - targetArchitecture: arm64 - targetRid: ${{ variables.linuxMuslArm64Rid }} - extraProperties: /p:DotNetBuildMonoCrossAOT=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: AzureLinux_x64_Cross_ShortStack_Alpine_NativeAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Linux }} - container: - name: ${{ variables.azurelinuxX64AlpineCrossContainerName }} - image: ${{ variables.azurelinuxX64AlpineCrossContainerImage }} - crossRootFs: '/crossrootfs/x64' - targetOS: linux-musl - targetArchitecture: x64 - targetRid: ${{ variables.linuxMuslX64Rid }} - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: AzureLinux_x64_Cross_ShortStack_Alpine_NativeAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Linux }} - container: - name: ${{ variables.azurelinuxArmAlpineCrossContainerName }} - image: ${{ variables.azurelinuxArmAlpineCrossContainerImage }} - crossRootFs: '/crossrootfs/arm' - targetOS: linux-musl - targetArchitecture: arm - targetRid: ${{ variables.linuxMuslArmRid }} - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: AzureLinux_x64_Cross_ShortStack_Alpine_NativeAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Linux }} - container: - name: ${{ variables.azurelinuxArm64AlpineCrossContainerName }} - image: ${{ variables.azurelinuxArm64AlpineCrossContainerImage }} - crossRootFs: '/crossrootfs/arm64' - targetOS: linux-musl - targetArchitecture: arm64 - targetRid: ${{ variables.linuxMuslArm64Rid }} - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: AzureLinux_x64_Cross_ShortStack_Mono_CrossAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Linux_Shortstack }} - container: - name: ${{ variables.azurelinuxX64CrossContainerName }} - image: ${{ variables.azurelinuxX64CrossContainerImage }} - crossRootFs: '/crossrootfs/x64' - targetOS: linux - targetArchitecture: x64 - extraProperties: /p:DotNetBuildMonoCrossAOT=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: AzureLinux_x64_ShortStack_NativeAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Linux_Shortstack }} - container: - name: ${{ variables.azurelinuxX64CrossContainerName }} - image: ${{ variables.azurelinuxX64CrossContainerImage }} - crossRootFs: '/crossrootfs/x64' - targetOS: linux - targetArchitecture: x64 - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: AzureLinux_x64_Cross_ShortStack_Mono_CrossAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Linux_Shortstack }} - container: - name: ${{ variables.azurelinuxArm64CrossContainerName }} - image: ${{ variables.azurelinuxArm64CrossContainerImage }} - crossRootFs: '/crossrootfs/arm64' - targetOS: linux - targetArchitecture: arm64 - extraProperties: /p:DotNetBuildMonoCrossAOT=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: AzureLinux_x64_Cross_ShortStack_Mono_LLVMAOT + buildName: AzureLinux_x64_Cross_Shortstack_Mono_LLVMAOT isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Linux_Shortstack }} container: name: ${{ variables.azurelinuxArm64CrossContainerName }} @@ -1102,214 +784,59 @@ stages: targetOS: linux targetArchitecture: arm64 extraProperties: /p:DotNetBuildMonoEnableLLVM=true /p:DotNetBuildMonoAOTEnableLLVM=true /p:DotNetBuildMonoBundleLLVMOptimizer=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: AzureLinux_x64_ShortStack_NativeAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Linux_Shortstack }} - container: - name: ${{ variables.azurelinuxArm64CrossContainerName }} - image: ${{ variables.azurelinuxArm64CrossContainerImage }} - crossRootFs: '/crossrootfs/arm64' - targetOS: linux - targetArchitecture: arm64 - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - template: ../jobs/vmr-build.yml parameters: buildName: OSX isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Mac }} targetOS: osx targetArchitecture: arm64 - - template: ../jobs/vmr-build.yml - parameters: - buildName: OSX_Mono - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Mac }} - useMonoRuntime: true - targetOS: osx - targetArchitecture: arm64 - - - template: ../jobs/vmr-build.yml - parameters: - buildName: OSX_ShortStack_Mono_CrossAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Mac }} - targetOS: osx - targetArchitecture: x64 - extraProperties: /p:DotNetBuildMonoCrossAOT=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: OSX_ShortStack_Mono_CrossAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Mac }} - targetOS: osx - targetArchitecture: arm64 - extraProperties: /p:DotNetBuildMonoCrossAOT=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: OSX_ShortStack_NativeAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Mac }} - targetOS: osx - targetArchitecture: x64 - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: OSX_ShortStack_NativeAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Mac }} - targetOS: osx - targetArchitecture: arm64 - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - - template: ../jobs/vmr-build.yml parameters: buildName: Windows isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Windows }} targetOS: windows targetArchitecture: arm64 - - template: ../jobs/vmr-build.yml - parameters: - buildName: Windows_ShortStack_NativeAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Windows }} - targetOS: windows - targetArchitecture: arm64 - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: Windows_Mono - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Windows }} - useMonoRuntime: true - targetOS: windows - targetArchitecture: x64 - - - template: ../jobs/vmr-build.yml - parameters: - buildName: Windows_ShortStack_NativeAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Windows }} - targetOS: windows - targetArchitecture: x64 - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: Windows_ShortStack_Mono_CrossAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Windows }} - targetOS: windows - targetArchitecture: x64 - extraProperties: /p:DotNetBuildMonoCrossAOT=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: Windows_ShortStack_Mono_CrossAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Windows }} - targetOS: windows - targetArchitecture: arm64 - extraProperties: /p:DotNetBuildMonoCrossAOT=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: Windows - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Windows }} - targetOS: windows - targetArchitecture: x86 - - - template: ../jobs/vmr-build.yml - parameters: - buildName: Windows_ShortStack_NativeAOT - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Windows }} - targetOS: windows - targetArchitecture: x86 - extraProperties: /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - runTests: false - - - template: ../jobs/vmr-build.yml - parameters: - buildName: Windows_Mono - isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} - vmrBranch: ${{ variables.VmrBranch }} - pool: ${{ parameters.pool_Windows }} - useMonoRuntime: true - targetOS: windows - targetArchitecture: x86 - - template: ../jobs/vmr-build.yml parameters: buildName: Windows_Pgo isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: false pool: ${{ parameters.pool_Windows }} targetOS: windows targetArchitecture: x64 extraProperties: /p:PgoInstrument=true - runTests: false - sign: false - template: ../jobs/vmr-build.yml parameters: buildName: Windows_Pgo isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: false pool: ${{ parameters.pool_Windows }} targetOS: windows targetArchitecture: x86 extraProperties: /p:PgoInstrument=true - runTests: false - sign: false - template: ../jobs/vmr-build.yml parameters: buildName: Windows_Pgo isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: false pool: ${{ parameters.pool_Windows }} targetOS: windows targetArchitecture: arm64 extraProperties: /p:PgoInstrument=true - runTests: false - sign: false # Build Pass 2 verticals @@ -1318,10 +845,10 @@ stages: buildName: Windows isBuiltFromVmr: ${{ parameters.isBuiltFromVmr }} vmrBranch: ${{ variables.VmrBranch }} + sign: ${{ variables.signEnabled }} pool: ${{ parameters.pool_Windows }} targetOS: windows targetArchitecture: x64 - runTests: false buildPass: 2 reuseBuildArtifactsFrom: - Windows_x64 @@ -1366,3 +893,18 @@ stages: dotNetBuildPass: final primaryDependentJob: Windows_x64 outputFolder: $(Build.ArtifactStagingDirectory)/artifacts + +### VALIDATION ### +- ${{ if and(parameters.isBuiltFromVmr, not(parameters.isSourceOnlyBuild), eq(variables['System.TeamProject'], 'internal'), eq(variables.signEnabled, 'true')) }}: + - stage: VMR_Validation + displayName: VMR Validation + dependsOn: VMR_Final_Join + jobs: + - job: ValidateSigning + displayName: Validate Signing + pool: ${{ parameters.pool_Windows }} + timeoutInMinutes: 240 + steps: + - template: ../steps/vmr-validate-signing.yml + parameters: + continueOnError: true diff --git a/eng/pipelines/templates/steps/vmr-validate-signing.yml b/eng/pipelines/templates/steps/vmr-validate-signing.yml new file mode 100644 index 000000000000..cee51d040259 --- /dev/null +++ b/eng/pipelines/templates/steps/vmr-validate-signing.yml @@ -0,0 +1,26 @@ +parameters: +- name: continueOnError + type: boolean + default: false + +steps: +- task: DownloadBuildArtifacts@1 + inputs: + artifactName: 'PackageArtifacts' + downloadPath: $(Build.ArtifactStagingDirectory) + checkDownloadedFiles: true + displayName: Download Package Artifacts + +# This is necessary whenever we want to publish/restore to an AzDO private feed +# Since sdk-task.ps1 tries to restore packages we need to do this authentication here +# otherwise it'll complain about accessing a private feed. +- task: NuGetAuthenticate@1 + displayName: 'Authenticate to AzDO Feeds' + +- task: PowerShell@2 + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task SigningValidation -restore -msbuildEngine vs + /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' + displayName: Validate Signing of Packages + continueOnError: ${{ parameters.continueOnError }} diff --git a/eng/pipelines/templates/variables/vmr-build.yml b/eng/pipelines/templates/variables/vmr-build.yml index 935c01099a5b..f49db6b7e54f 100644 --- a/eng/pipelines/templates/variables/vmr-build.yml +++ b/eng/pipelines/templates/variables/vmr-build.yml @@ -4,6 +4,11 @@ parameters: type: string default: '' +- name: desiredSigning + displayName: Signed/unsigned/default signing parameters + type: string + default: '' + variables: - ${{ if ne(parameters.vmrBranch, '') }}: - name: VmrBranch @@ -18,6 +23,42 @@ variables: - name: defaultContainerOptions value: --privileged +- name: isOfficialBuild + value: ${{ and(eq(variables['System.TeamProject'], 'internal'), notin(variables['Build.Reason'], 'PullRequest')) }} + +- name: officialBuildParameter + ${{ if eq(variables['isOfficialBuild'], true) }}: + value: /p:OfficialBuildId=$(Build.BuildNumber) + ${{ else }}: + value: '' + +- ${{ if eq(parameters.desiredSigning, 'Signed') }}: + - name: signEnabled + value: true +- ${{ if eq(parameters.desiredSigning, 'Unsigned') }}: + - name: signEnabled + value: false +- ${{ if or(startsWith(parameters.desiredSigning, 'Default'), eq(parameters.desiredSigning, '')) }}: + # Always sign on the public project (will be dry-run signing) + - ${{ if eq(variables['System.TeamProject'], 'public') }}: + - name: signEnabled + value: true + # Always sign in pull requests (dry run) + - ${{ elseif eq(variables['Build.Reason'], 'PullRequest') }}: + - name: signEnabled + value: true + # Pass sign on the internal project if the, branch is a main or release branch + - ${{ elseif and(eq(variables['System.TeamProject'], 'internal'), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), startsWith(variables['Build.SourceBranch'], 'refs/heads/internal/release/'), and(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), contains(variables['Build.SourceBranch'], '-preview')))) }}: + - name: signEnabled + value: true + # Do not sign otherwise. + - ${{ else }}: + - name: signEnabled + value: false +- ${{ else }}: + - name: signEnabled + value: false + - name: almaLinuxContainerName value: almaLinuxContainer - name: almaLinuxContainerImage @@ -51,52 +92,52 @@ variables: - name: azurelinuxX64CrossContainerName value: azurelinuxX64CrossContainer - name: azurelinuxX64CrossContainerImage - value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net9.0-cross-amd64 + value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-amd64 - name: azurelinuxArmCrossContainerName value: azurelinuxArmCrossContainer - name: azurelinuxArmCrossContainerImage - value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net9.0-cross-arm + value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-arm - name: azurelinuxArm64CrossContainerName value: azurelinuxArm64CrossContainer - name: azurelinuxArm64CrossContainerImage - value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net9.0-cross-arm64 + value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-arm64 -- name: azurelinuxX64AlpineCrossContainerName - value: azurelinuxX64AlpineCrossContainer -- name: azurelinuxX64AlpineCrossContainerImage - value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net9.0-cross-amd64-alpine +- name: azurelinuxX64MuslCrossContainerName + value: azurelinuxX64MuslCrossContainer +- name: azurelinuxX64MuslCrossContainerImage + value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-amd64-musl -- name: azurelinuxArmAlpineCrossContainerName - value: azurelinuxArmAlpineCrossContainer -- name: azurelinuxArmAlpineCrossContainerImage - value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net9.0-cross-arm-alpine +- name: azurelinuxArmMuslCrossContainerName + value: azurelinuxArmMuslCrossContainer +- name: azurelinuxArmMuslCrossContainerImage + value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-arm-musl -- name: azurelinuxArm64AlpineCrossContainerName - value: azurelinuxArm64AlpineCrossContainer -- name: azurelinuxArm64AlpineCrossContainerImage - value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net9.0-cross-arm64-alpine +- name: azurelinuxArm64MuslCrossContainerName + value: azurelinuxArm64MuslCrossContainer +- name: azurelinuxArm64MuslCrossContainerImage + value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-arm64-musl - name: androidCrossContainerName value: androidCrossContainer - name: androidCrossContainerImage - value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net9.0-cross-android-amd64 + value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-android-amd64 - name: linuxBionicCrossContainerName value: linuxBionicCrossContainer - name: linuxBionicCrossContainerImage - value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net9.0-android-openssl + value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-android-openssl-amd64 - name: browserCrossContainerName value: browserCrossContainer - name: browserCrossContainerImage - value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net9.0-webassembly-amd64 + value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-webassembly-amd64 - name: wasiCrossContainerName value: wasiCrossContainer - name: wasiCrossContainerImage - value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net9.0-webassembly-amd64 + value: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-webassembly-amd64 - name: almaLinuxName value: AlmaLinux8 diff --git a/eng/pipelines/vmr-build-pr.yml b/eng/pipelines/vmr-build-pr.yml index 20352fae76fa..9abe336f5371 100644 --- a/eng/pipelines/vmr-build-pr.yml +++ b/eng/pipelines/vmr-build-pr.yml @@ -39,6 +39,13 @@ parameters: variables: - template: /eng/common/templates/variables/pool-providers.yml@self +- ${{ if eq(variables['System.TeamProject'], 'public') }}: + - name: skipComponentGovernanceDetection # we run CG on internal builds only + value: true + + - name: Codeql.Enabled # we run CodeQL on internal builds only + value: false + - ${{ if ne(parameters.vmrBranch, ' ') }}: - name: VmrBranch value: ${{ replace(parameters.vmrBranch, ' ', '') }} diff --git a/github-merge-flow.jsonc b/github-merge-flow.jsonc index f14a2eb445f1..fe686d5ff56b 100644 --- a/github-merge-flow.jsonc +++ b/github-merge-flow.jsonc @@ -21,8 +21,13 @@ "MergeToBranch": "release/9.0.2xx", "ExtraSwitches": "-QuietComments" }, - // Automate opening PRs to merge sdk repos from release/9.0.2xx to main + // Automate opening PRs to merge sdk repos from release/9.0.2xx to release/9.0.3xx "release/9.0.2xx":{ + "MergeToBranch": "release/9.0.3xx", + "ExtraSwitches": "-QuietComments" + }, + // Automate opening PRs to merge sdk repos from release/9.0.3xx to main + "release/9.0.3xx":{ "MergeToBranch": "main", "ExtraSwitches": "-QuietComments" } diff --git a/global.json b/global.json index 7d56494ca0cf..069338eb4678 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "tools": { - "dotnet": "10.0.100-alpha.1.24573.1", + "dotnet": "10.0.100-alpha.1.25077.2", "runtimes": { "dotnet": [ "$(VSRedistCommonNetCoreSharedFrameworkx64100PackageVersion)" @@ -17,8 +17,8 @@ "cmake": "latest" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25061.1", - "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.25061.1", + "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25080.7", + "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.25080.7", "Microsoft.Build.NoTargets": "3.7.0", "Microsoft.DotNet.CMake.Sdk": "9.0.0-beta.24217.1" } diff --git a/sdk.sln b/sdk.sln index 2480a90d380b..93cacf6e7274 100644 --- a/sdk.sln +++ b/sdk.sln @@ -73,8 +73,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Cli", "Cli", "{9CEF03F6-1A6 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Cli.Utils", "src\Cli\Microsoft.DotNet.Cli.Utils\Microsoft.DotNet.Cli.Utils.csproj", "{CC25E192-70AD-4D91-B288-3AD40065DBAC}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Cli.Sln.Internal", "src\Cli\Microsoft.DotNet.Cli.Sln.Internal\Microsoft.DotNet.Cli.Sln.Internal.csproj", "{2119E6E5-2B75-402A-AFF3-3E7E7B671B9B}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.InternalAbstractions", "src\Cli\Microsoft.DotNet.InternalAbstractions\Microsoft.DotNet.InternalAbstractions.csproj", "{0FA6CEE9-7A97-4036-8D48-39BA4F85118E}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Configurer", "src\Cli\Microsoft.DotNet.Configurer\Microsoft.DotNet.Configurer.csproj", "{B22C90C9-BA46-4F07-9613-253DD01E3EFF}" @@ -109,8 +107,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArgumentForwarding.Tests", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EndToEnd.Tests", "test\EndToEnd.Tests\EndToEnd.Tests.csproj", "{A0EFB2CB-517F-4746-902E-D0EBEFFBD89B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Cli.Sln.Internal.Tests", "test\Microsoft.DotNet.Cli.Sln.Internal.Tests\Microsoft.DotNet.Cli.Sln.Internal.Tests.csproj", "{82D910C3-A5E2-41F0-A142-F4F2D770CB59}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Cli.Utils.Tests", "test\Microsoft.DotNet.Cli.Utils.Tests\Microsoft.DotNet.Cli.Utils.Tests.csproj", "{C34FB893-2320-41A3-9D38-0061C22A6464}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.MSBuildSdkResolver.Tests", "test\Microsoft.DotNet.MSBuildSdkResolver.Tests\Microsoft.DotNet.MSBuildSdkResolver.Tests.csproj", "{0AE2AB83-1F0D-4E04-9C8D-5C35CE97FDDC}" @@ -517,6 +513,10 @@ Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Microsoft.DotNet.HotReload. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.DotNet.HotReload.Agent.Package", "src\BuiltInTools\HotReloadAgent\Microsoft.DotNet.HotReload.Agent.Package.csproj", "{2FF79F82-60C1-349A-4726-7783D5A6D5DF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.DotNet.HotReload.Agent.PipeRpc.Package", "src\BuiltInTools\HotReloadAgent.PipeRpc\Microsoft.DotNet.HotReload.Agent.PipeRpc.Package.csproj", "{692B71D8-9C31-D1EE-6C1B-570A12B18E39}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Microsoft.DotNet.HotReload.Agent.PipeRpc", "src\BuiltInTools\HotReloadAgent.PipeRpc\Microsoft.DotNet.HotReload.Agent.PipeRpc.shproj", "{FA3C7F91-42A2-45AD-897C-F646B081016C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -579,10 +579,6 @@ Global {CC25E192-70AD-4D91-B288-3AD40065DBAC}.Debug|Any CPU.Build.0 = Debug|Any CPU {CC25E192-70AD-4D91-B288-3AD40065DBAC}.Release|Any CPU.ActiveCfg = Release|Any CPU {CC25E192-70AD-4D91-B288-3AD40065DBAC}.Release|Any CPU.Build.0 = Release|Any CPU - {2119E6E5-2B75-402A-AFF3-3E7E7B671B9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2119E6E5-2B75-402A-AFF3-3E7E7B671B9B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2119E6E5-2B75-402A-AFF3-3E7E7B671B9B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2119E6E5-2B75-402A-AFF3-3E7E7B671B9B}.Release|Any CPU.Build.0 = Release|Any CPU {0FA6CEE9-7A97-4036-8D48-39BA4F85118E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0FA6CEE9-7A97-4036-8D48-39BA4F85118E}.Debug|Any CPU.Build.0 = Debug|Any CPU {0FA6CEE9-7A97-4036-8D48-39BA4F85118E}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -647,10 +643,6 @@ Global {A0EFB2CB-517F-4746-902E-D0EBEFFBD89B}.Debug|Any CPU.Build.0 = Debug|Any CPU {A0EFB2CB-517F-4746-902E-D0EBEFFBD89B}.Release|Any CPU.ActiveCfg = Release|Any CPU {A0EFB2CB-517F-4746-902E-D0EBEFFBD89B}.Release|Any CPU.Build.0 = Release|Any CPU - {82D910C3-A5E2-41F0-A142-F4F2D770CB59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {82D910C3-A5E2-41F0-A142-F4F2D770CB59}.Debug|Any CPU.Build.0 = Debug|Any CPU - {82D910C3-A5E2-41F0-A142-F4F2D770CB59}.Release|Any CPU.ActiveCfg = Release|Any CPU - {82D910C3-A5E2-41F0-A142-F4F2D770CB59}.Release|Any CPU.Build.0 = Release|Any CPU {C34FB893-2320-41A3-9D38-0061C22A6464}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C34FB893-2320-41A3-9D38-0061C22A6464}.Debug|Any CPU.Build.0 = Debug|Any CPU {C34FB893-2320-41A3-9D38-0061C22A6464}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -979,6 +971,10 @@ Global {2FF79F82-60C1-349A-4726-7783D5A6D5DF}.Debug|Any CPU.Build.0 = Debug|Any CPU {2FF79F82-60C1-349A-4726-7783D5A6D5DF}.Release|Any CPU.ActiveCfg = Release|Any CPU {2FF79F82-60C1-349A-4726-7783D5A6D5DF}.Release|Any CPU.Build.0 = Release|Any CPU + {692B71D8-9C31-D1EE-6C1B-570A12B18E39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {692B71D8-9C31-D1EE-6C1B-570A12B18E39}.Debug|Any CPU.Build.0 = Debug|Any CPU + {692B71D8-9C31-D1EE-6C1B-570A12B18E39}.Release|Any CPU.ActiveCfg = Release|Any CPU + {692B71D8-9C31-D1EE-6C1B-570A12B18E39}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1002,7 +998,6 @@ Global {E740A596-2CAE-476C-8062-49705C3A9CF0} = {580D1AE7-AA8F-4912-8B76-105594E00B3B} {9CEF03F6-1A61-431A-8ABD-9095974629AE} = {22AB674F-ED91-4FBC-BFEE-8A1E82F9F05E} {CC25E192-70AD-4D91-B288-3AD40065DBAC} = {9CEF03F6-1A61-431A-8ABD-9095974629AE} - {2119E6E5-2B75-402A-AFF3-3E7E7B671B9B} = {9CEF03F6-1A61-431A-8ABD-9095974629AE} {0FA6CEE9-7A97-4036-8D48-39BA4F85118E} = {9CEF03F6-1A61-431A-8ABD-9095974629AE} {B22C90C9-BA46-4F07-9613-253DD01E3EFF} = {9CEF03F6-1A61-431A-8ABD-9095974629AE} {D62591F3-ED86-4014-B765-7CDA47F55EE2} = {9CEF03F6-1A61-431A-8ABD-9095974629AE} @@ -1020,7 +1015,6 @@ Global {587A6639-FA2A-498C-8FA2-F77925DB732B} = {580D1AE7-AA8F-4912-8B76-105594E00B3B} {2D8AA9EA-3013-47DE-B2DD-E074F67467ED} = {580D1AE7-AA8F-4912-8B76-105594E00B3B} {A0EFB2CB-517F-4746-902E-D0EBEFFBD89B} = {580D1AE7-AA8F-4912-8B76-105594E00B3B} - {82D910C3-A5E2-41F0-A142-F4F2D770CB59} = {580D1AE7-AA8F-4912-8B76-105594E00B3B} {C34FB893-2320-41A3-9D38-0061C22A6464} = {580D1AE7-AA8F-4912-8B76-105594E00B3B} {0AE2AB83-1F0D-4E04-9C8D-5C35CE97FDDC} = {580D1AE7-AA8F-4912-8B76-105594E00B3B} {3D20D19D-74FB-4A43-B78C-B0AF90A696A0} = {580D1AE7-AA8F-4912-8B76-105594E00B3B} @@ -1159,6 +1153,8 @@ Global {8D6A9984-118D-4415-A8FA-AB1F26CF5C44} = {3FA6F1CB-295B-4414-B18F-93845917A8CD} {418B10BD-CA42-49F3-8F4A-D8CC90C8A17D} = {71A9F549-0EB6-41F9-BC16-4A6C5007FC91} {2FF79F82-60C1-349A-4726-7783D5A6D5DF} = {71A9F549-0EB6-41F9-BC16-4A6C5007FC91} + {692B71D8-9C31-D1EE-6C1B-570A12B18E39} = {71A9F549-0EB6-41F9-BC16-4A6C5007FC91} + {FA3C7F91-42A2-45AD-897C-F646B081016C} = {71A9F549-0EB6-41F9-BC16-4A6C5007FC91} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {FB8F26CE-4DE6-433F-B32A-79183020BBD6} @@ -1166,12 +1162,15 @@ Global GlobalSection(SharedMSBuildProjectFiles) = preSolution src\Compatibility\ApiCompat\Microsoft.DotNet.ApiCompat.Shared\Microsoft.DotNet.ApiCompat.Shared.projitems*{03c5a84a-982b-4f38-ac73-ab832c645c4a}*SharedItemsImports = 5 src\Compatibility\ApiCompat\Microsoft.DotNet.ApiCompat.Shared\Microsoft.DotNet.ApiCompat.Shared.projitems*{0a3c9afd-f6e6-4a5d-83fb-93bf66732696}*SharedItemsImports = 5 + src\BuiltInTools\HotReloadAgent.PipeRpc\Microsoft.DotNet.HotReload.Agent.PipeRpc.projitems*{1bbfa19c-03f0-4d27-9d0d-0f8172642107}*SharedItemsImports = 5 src\BuiltInTools\HotReloadAgent\Microsoft.DotNet.HotReload.Agent.projitems*{1bbfa19c-03f0-4d27-9d0d-0f8172642107}*SharedItemsImports = 5 src\BuiltInTools\AspireService\Microsoft.WebTools.AspireService.projitems*{1f0b4b3c-dc88-4740-b04f-1707102e9930}*SharedItemsImports = 5 src\BuiltInTools\HotReloadAgent\Microsoft.DotNet.HotReload.Agent.projitems*{418b10bd-ca42-49f3-8f4a-d8cc90c8a17d}*SharedItemsImports = 13 src\BuiltInTools\AspireService\Microsoft.WebTools.AspireService.projitems*{445efbd5-6730-4f09-943d-278e77501ffd}*SharedItemsImports = 5 + src\BuiltInTools\HotReloadAgent.PipeRpc\Microsoft.DotNet.HotReload.Agent.PipeRpc.projitems*{445efbd5-6730-4f09-943d-278e77501ffd}*SharedItemsImports = 5 src\BuiltInTools\AspireService\Microsoft.WebTools.AspireService.projitems*{94c8526e-dcc2-442f-9868-3dd0ba2688be}*SharedItemsImports = 13 src\Compatibility\ApiCompat\Microsoft.DotNet.ApiCompat.Shared\Microsoft.DotNet.ApiCompat.Shared.projitems*{9d36039f-d0a1-462f-85b4-81763c6b02cb}*SharedItemsImports = 13 src\Compatibility\ApiCompat\Microsoft.DotNet.ApiCompat.Shared\Microsoft.DotNet.ApiCompat.Shared.projitems*{a9103b98-d888-4260-8a05-fa36f640698a}*SharedItemsImports = 5 + src\BuiltInTools\HotReloadAgent.PipeRpc\Microsoft.DotNet.HotReload.Agent.PipeRpc.projitems*{fa3c7f91-42a2-45ad-897c-f646b081016c}*SharedItemsImports = 13 EndGlobalSection EndGlobal diff --git a/source-build.slnf b/source-build.slnf index 8ee120cc0e10..ff429db4dbae 100644 --- a/source-build.slnf +++ b/source-build.slnf @@ -8,7 +8,6 @@ "src\\BuiltInTools\\DotNetDeltaApplier\\Microsoft.Extensions.DotNetDeltaApplier.csproj", "src\\BuiltInTools\\DotNetWatchTasks\\DotNetWatchTasks.csproj", "src\\BuiltInTools\\dotnet-watch\\dotnet-watch.csproj", - "src\\Cli\\Microsoft.DotNet.Cli.Sln.Internal\\Microsoft.DotNet.Cli.Sln.Internal.csproj", "src\\Cli\\Microsoft.DotNet.Cli.Utils\\Microsoft.DotNet.Cli.Utils.csproj", "src\\Cli\\Microsoft.DotNet.Configurer\\Microsoft.DotNet.Configurer.csproj", "src\\Cli\\Microsoft.DotNet.InternalAbstractions\\Microsoft.DotNet.InternalAbstractions.csproj", diff --git a/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.6_0.targets b/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.6_0.targets index ffd2cb044182..46e2ef8cd2d1 100644 --- a/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.6_0.targets +++ b/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.6_0.targets @@ -44,6 +44,7 @@ Copyright (c) .NET Foundation. All rights reserved. false false true + true false false false diff --git a/src/BuiltInTools/DotNetDeltaApplier/Microsoft.Extensions.DotNetDeltaApplier.csproj b/src/BuiltInTools/DotNetDeltaApplier/Microsoft.Extensions.DotNetDeltaApplier.csproj index 12de0ae0c4fa..a663b6440dc0 100644 --- a/src/BuiltInTools/DotNetDeltaApplier/Microsoft.Extensions.DotNetDeltaApplier.csproj +++ b/src/BuiltInTools/DotNetDeltaApplier/Microsoft.Extensions.DotNetDeltaApplier.csproj @@ -1,5 +1,6 @@  + + netstandard2.0 + false + none + false + enable + preview + + + true + true + Microsoft.DotNet.HotReload.Agent.PipeRpc + false + + Package containing sources of Hot Reload agent pipe RPC. + + + $(NoWarn);NU5128 + + + + + + + + + + + + + + + + + + + + diff --git a/src/BuiltInTools/HotReloadAgent.PipeRpc/Microsoft.DotNet.HotReload.Agent.PipeRpc.projitems b/src/BuiltInTools/HotReloadAgent.PipeRpc/Microsoft.DotNet.HotReload.Agent.PipeRpc.projitems new file mode 100644 index 000000000000..f1969e528c57 --- /dev/null +++ b/src/BuiltInTools/HotReloadAgent.PipeRpc/Microsoft.DotNet.HotReload.Agent.PipeRpc.projitems @@ -0,0 +1,14 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + {FA3C7F91-42A2-45AD-897C-F646B081016C} + + + Microsoft.DotNet.HotReload + + + + + \ No newline at end of file diff --git a/src/BuiltInTools/HotReloadAgent.PipeRpc/Microsoft.DotNet.HotReload.Agent.PipeRpc.shproj b/src/BuiltInTools/HotReloadAgent.PipeRpc/Microsoft.DotNet.HotReload.Agent.PipeRpc.shproj new file mode 100644 index 000000000000..cf55004689ca --- /dev/null +++ b/src/BuiltInTools/HotReloadAgent.PipeRpc/Microsoft.DotNet.HotReload.Agent.PipeRpc.shproj @@ -0,0 +1,13 @@ + + + + FA3C7F91-42A2-45AD-897C-F646B081016C + 14.0 + + + + + + + + \ No newline at end of file diff --git a/src/BuiltInTools/HotReloadAgent.PipeRpc/NamedPipeContract.cs b/src/BuiltInTools/HotReloadAgent.PipeRpc/NamedPipeContract.cs new file mode 100644 index 000000000000..62686ddc226c --- /dev/null +++ b/src/BuiltInTools/HotReloadAgent.PipeRpc/NamedPipeContract.cs @@ -0,0 +1,190 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.HotReload; + +internal interface IRequest +{ + RequestType Type { get; } + ValueTask WriteAsync(Stream stream, CancellationToken cancellationToken); +} + +internal interface IUpdateRequest : IRequest +{ +} + +internal enum RequestType +{ + ManagedCodeUpdate = 1, + StaticAssetUpdate = 2, + InitialUpdatesCompleted = 3, +} + +internal readonly struct ManagedCodeUpdateRequest(IReadOnlyList deltas, ResponseLoggingLevel responseLoggingLevel) : IUpdateRequest +{ + private const byte Version = 4; + + public IReadOnlyList Deltas { get; } = deltas; + public ResponseLoggingLevel ResponseLoggingLevel { get; } = responseLoggingLevel; + public RequestType Type => RequestType.ManagedCodeUpdate; + + public async ValueTask WriteAsync(Stream stream, CancellationToken cancellationToken) + { + await stream.WriteAsync(Version, cancellationToken); + await stream.WriteAsync(Deltas.Count, cancellationToken); + + foreach (var delta in Deltas) + { + await stream.WriteAsync(delta.ModuleId, cancellationToken); + await stream.WriteByteArrayAsync(delta.MetadataDelta, cancellationToken); + await stream.WriteByteArrayAsync(delta.ILDelta, cancellationToken); + await stream.WriteByteArrayAsync(delta.PdbDelta, cancellationToken); + await stream.WriteAsync(delta.UpdatedTypes, cancellationToken); + } + + await stream.WriteAsync((byte)ResponseLoggingLevel, cancellationToken); + } + + public static async ValueTask ReadAsync(Stream stream, CancellationToken cancellationToken) + { + var version = await stream.ReadByteAsync(cancellationToken); + if (version != Version) + { + throw new NotSupportedException($"Unsupported version {version}."); + } + + var count = await stream.ReadInt32Async(cancellationToken); + + var deltas = new UpdateDelta[count]; + for (var i = 0; i < count; i++) + { + var moduleId = await stream.ReadGuidAsync(cancellationToken); + var metadataDelta = await stream.ReadByteArrayAsync(cancellationToken); + var ilDelta = await stream.ReadByteArrayAsync(cancellationToken); + var pdbDelta = await stream.ReadByteArrayAsync(cancellationToken); + var updatedTypes = await stream.ReadIntArrayAsync(cancellationToken); + + deltas[i] = new UpdateDelta(moduleId, metadataDelta: metadataDelta, ilDelta: ilDelta, pdbDelta: pdbDelta, updatedTypes); + } + + var responseLoggingLevel = (ResponseLoggingLevel)await stream.ReadByteAsync(cancellationToken); + return new ManagedCodeUpdateRequest(deltas, responseLoggingLevel: responseLoggingLevel); + } +} + +internal readonly struct UpdateResponse(IReadOnlyCollection<(string message, AgentMessageSeverity severity)> log, bool success) +{ + public async ValueTask WriteAsync(Stream stream, CancellationToken cancellationToken) + { + await stream.WriteAsync(success, cancellationToken); + await stream.WriteAsync(log.Count, cancellationToken); + + foreach (var (message, severity) in log) + { + await stream.WriteAsync(message, cancellationToken); + await stream.WriteAsync((byte)severity, cancellationToken); + } + } + + public static async ValueTask<(bool success, IAsyncEnumerable<(string message, AgentMessageSeverity severity)>)> ReadAsync( + Stream stream, CancellationToken cancellationToken) + { + var success = await stream.ReadBooleanAsync(cancellationToken); + var log = ReadLogAsync(cancellationToken); + return (success, log); + + async IAsyncEnumerable<(string message, AgentMessageSeverity severity)> ReadLogAsync([EnumeratorCancellation] CancellationToken cancellationToken) + { + var entryCount = await stream.ReadInt32Async(cancellationToken); + + for (var i = 0; i < entryCount; i++) + { + var message = await stream.ReadStringAsync(cancellationToken); + var severity = (AgentMessageSeverity)await stream.ReadByteAsync(cancellationToken); + yield return (message, severity); + } + } + } +} + +internal readonly struct ClientInitializationResponse(string capabilities) +{ + private const byte Version = 0; + + public string Capabilities { get; } = capabilities; + + public async ValueTask WriteAsync(Stream stream, CancellationToken cancellationToken) + { + await stream.WriteAsync(Version, cancellationToken); + await stream.WriteAsync(Capabilities, cancellationToken); + } + + public static async ValueTask ReadAsync(Stream stream, CancellationToken cancellationToken) + { + var version = await stream.ReadByteAsync(cancellationToken); + if (version != Version) + { + throw new NotSupportedException($"Unsupported version {version}."); + } + + var capabilities = await stream.ReadStringAsync(cancellationToken); + return new ClientInitializationResponse(capabilities); + } +} + +internal readonly struct StaticAssetUpdateRequest( + string assemblyName, + string relativePath, + byte[] contents, + bool isApplicationProject, + ResponseLoggingLevel responseLoggingLevel) : IUpdateRequest +{ + private const byte Version = 2; + + public string AssemblyName { get; } = assemblyName; + public bool IsApplicationProject { get; } = isApplicationProject; + public string RelativePath { get; } = relativePath; + public byte[] Contents { get; } = contents; + public ResponseLoggingLevel ResponseLoggingLevel { get; } = responseLoggingLevel; + + public RequestType Type => RequestType.StaticAssetUpdate; + + public async ValueTask WriteAsync(Stream stream, CancellationToken cancellationToken) + { + await stream.WriteAsync(Version, cancellationToken); + await stream.WriteAsync(AssemblyName, cancellationToken); + await stream.WriteAsync(IsApplicationProject, cancellationToken); + await stream.WriteAsync(RelativePath, cancellationToken); + await stream.WriteByteArrayAsync(Contents, cancellationToken); + await stream.WriteAsync((byte)ResponseLoggingLevel, cancellationToken); + } + + public static async ValueTask ReadAsync(Stream stream, CancellationToken cancellationToken) + { + var version = await stream.ReadByteAsync(cancellationToken); + if (version != Version) + { + throw new NotSupportedException($"Unsupported version {version}."); + } + + var assemblyName = await stream.ReadStringAsync(cancellationToken); + var isApplicationProject = await stream.ReadBooleanAsync(cancellationToken); + var relativePath = await stream.ReadStringAsync(cancellationToken); + var contents = await stream.ReadByteArrayAsync(cancellationToken); + var responseLoggingLevel = (ResponseLoggingLevel)await stream.ReadByteAsync(cancellationToken); + + return new StaticAssetUpdateRequest( + assemblyName: assemblyName, + relativePath: relativePath, + contents: contents, + isApplicationProject, + responseLoggingLevel); + } +} diff --git a/src/BuiltInTools/HotReloadAgent.PipeRpc/StreamExtensions.cs b/src/BuiltInTools/HotReloadAgent.PipeRpc/StreamExtensions.cs new file mode 100644 index 000000000000..4169cae79e38 --- /dev/null +++ b/src/BuiltInTools/HotReloadAgent.PipeRpc/StreamExtensions.cs @@ -0,0 +1,274 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +using System; +using System.Buffers; +using System.Buffers.Binary; +using System.IO; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.HotReload; + +/// +/// Implements async read/write helpers that provide functionality of and . +/// See https://github.com/dotnet/runtime/issues/17229 +/// +internal static class StreamExtesions +{ + public static ValueTask WriteAsync(this Stream stream, bool value, CancellationToken cancellationToken) + => WriteAsync(stream, (byte)(value ? 1 : 0), cancellationToken); + + public static async ValueTask WriteAsync(this Stream stream, byte value, CancellationToken cancellationToken) + { + var size = sizeof(byte); + var buffer = ArrayPool.Shared.Rent(minimumLength: size); + try + { + buffer[0] = value; + await stream.WriteAsync(buffer, offset: 0, count: size, cancellationToken); + } + finally + { + ArrayPool.Shared.Return(buffer); + } + } + + public static async ValueTask WriteAsync(this Stream stream, int value, CancellationToken cancellationToken) + { + var size = sizeof(int); + var buffer = ArrayPool.Shared.Rent(minimumLength: size); + try + { + BinaryPrimitives.WriteInt32LittleEndian(buffer, value); + await stream.WriteAsync(buffer, offset: 0, count: size, cancellationToken); + } + finally + { + ArrayPool.Shared.Return(buffer); + } + } + + public static ValueTask WriteAsync(this Stream stream, Guid value, CancellationToken cancellationToken) + => stream.WriteAsync(value.ToByteArray(), cancellationToken); + + public static async ValueTask WriteByteArrayAsync(this Stream stream, byte[] value, CancellationToken cancellationToken) + { + await stream.WriteAsync(value.Length, cancellationToken); + await stream.WriteAsync(value, cancellationToken); + } + + public static async ValueTask WriteAsync(this Stream stream, int[] value, CancellationToken cancellationToken) + { + var size = sizeof(int) * (value.Length + 1); + var buffer = ArrayPool.Shared.Rent(minimumLength: size); + try + { + BinaryPrimitives.WriteInt32LittleEndian(buffer, value.Length); + for (int i = 0; i < value.Length; i++) + { + BinaryPrimitives.WriteInt32LittleEndian(buffer.AsSpan((i + 1) * sizeof(int), sizeof(int)), value[i]); + } + + await stream.WriteAsync(buffer, offset: 0, count: size, cancellationToken); + } + finally + { + ArrayPool.Shared.Return(buffer); + } + } + + public static async ValueTask WriteAsync(this Stream stream, string value, CancellationToken cancellationToken) + { + var bytes = Encoding.UTF8.GetBytes(value); + await stream.Write7BitEncodedIntAsync(bytes.Length, cancellationToken); + await stream.WriteAsync(bytes, cancellationToken); + } + +#if !NET + public static async ValueTask WriteAsync(this Stream stream, byte[] value, CancellationToken cancellationToken) + => await stream.WriteAsync(value, offset: 0, count: value.Length, cancellationToken); +#endif + public static async ValueTask Write7BitEncodedIntAsync(this Stream stream, int value, CancellationToken cancellationToken) + { + uint uValue = (uint)value; + + while (uValue > 0x7Fu) + { + await stream.WriteAsync((byte)(uValue | ~0x7Fu), cancellationToken); + uValue >>= 7; + } + + await stream.WriteAsync((byte)uValue, cancellationToken); + } + + public static async ValueTask ReadBooleanAsync(this Stream stream, CancellationToken cancellationToken) + => await stream.ReadByteAsync(cancellationToken) != 0; + + public static async ValueTask ReadByteAsync(this Stream stream, CancellationToken cancellationToken) + { + int size = sizeof(byte); + var buffer = ArrayPool.Shared.Rent(minimumLength: size); + try + { + await ReadExactlyAsync(stream, buffer, size, cancellationToken); + return buffer[0]; + } + finally + { + ArrayPool.Shared.Return(buffer); + } + } + + public static async ValueTask ReadInt32Async(this Stream stream, CancellationToken cancellationToken) + { + int size = sizeof(int); + var buffer = ArrayPool.Shared.Rent(minimumLength: size); + try + { + await ReadExactlyAsync(stream, buffer, size, cancellationToken); + return BinaryPrimitives.ReadInt32LittleEndian(buffer); + } + finally + { + ArrayPool.Shared.Return(buffer); + } + } + + public static async ValueTask ReadGuidAsync(this Stream stream, CancellationToken cancellationToken) + { + const int size = 16; +#if NET + var buffer = ArrayPool.Shared.Rent(minimumLength: size); + + try + { + await ReadExactlyAsync(stream, buffer, size, cancellationToken); + return new Guid(buffer.AsSpan(0, size)); + } + finally + { + ArrayPool.Shared.Return(buffer); + } +#else + var buffer = new byte[size]; + await ReadExactlyAsync(stream, buffer, size, cancellationToken); + return new Guid(buffer); +#endif + } + + public static async ValueTask ReadByteArrayAsync(this Stream stream, CancellationToken cancellationToken) + { + var count = await stream.ReadInt32Async(cancellationToken); + if (count == 0) + { + return []; + } + + var bytes = new byte[count]; + await ReadExactlyAsync(stream, bytes, count, cancellationToken); + return bytes; + } + + public static async ValueTask ReadIntArrayAsync(this Stream stream, CancellationToken cancellationToken) + { + var count = await stream.ReadInt32Async(cancellationToken); + if (count == 0) + { + return []; + } + + var result = new int[count]; + int size = count * sizeof(int); + var buffer = ArrayPool.Shared.Rent(minimumLength: size); + try + { + await ReadExactlyAsync(stream, buffer, size, cancellationToken); + + for (var i = 0; i < count; i++) + { + result[i] = BinaryPrimitives.ReadInt32LittleEndian(buffer.AsSpan(i * sizeof(int))); + } + } + finally + { + ArrayPool.Shared.Return(buffer); + } + + return result; + } + + public static async ValueTask ReadStringAsync(this Stream stream, CancellationToken cancellationToken) + { + int size = await stream.Read7BitEncodedIntAsync(cancellationToken); + if (size < 0) + { + throw new InvalidDataException(); + } + + if (size == 0) + { + return string.Empty; + } + + var buffer = ArrayPool.Shared.Rent(minimumLength: size); + try + { + await ReadExactlyAsync(stream, buffer, size, cancellationToken); + return Encoding.UTF8.GetString(buffer, 0, size); + } + finally + { + ArrayPool.Shared.Return(buffer); + } + } + + public static async ValueTask Read7BitEncodedIntAsync(this Stream stream, CancellationToken cancellationToken) + { + const int MaxBytesWithoutOverflow = 4; + + uint result = 0; + byte b; + + for (int shift = 0; shift < MaxBytesWithoutOverflow * 7; shift += 7) + { + b = await stream.ReadByteAsync(cancellationToken); + result |= (b & 0x7Fu) << shift; + + if (b <= 0x7Fu) + { + return (int)result; + } + } + + // Read the 5th byte. Since we already read 28 bits, + // the value of this byte must fit within 4 bits (32 - 28), + // and it must not have the high bit set. + + b = await stream.ReadByteAsync(cancellationToken); + if (b > 0b_1111u) + { + throw new InvalidDataException(); + } + + result |= (uint)b << (MaxBytesWithoutOverflow * 7); + return (int)result; + } + + private static async ValueTask ReadExactlyAsync(this Stream stream, byte[] buffer, int size, CancellationToken cancellationToken) + { + int totalRead = 0; + while (totalRead < size) + { + int read = await stream.ReadAsync(buffer, offset: totalRead, count: size - totalRead, cancellationToken).ConfigureAwait(false); + if (read == 0) + { + throw new EndOfStreamException(); + } + + totalRead += read; + } + + return totalRead; + } +} diff --git a/src/BuiltInTools/HotReloadAgent/AgentEnvironmentVariables.cs b/src/BuiltInTools/HotReloadAgent/AgentEnvironmentVariables.cs new file mode 100644 index 000000000000..606e5be8f881 --- /dev/null +++ b/src/BuiltInTools/HotReloadAgent/AgentEnvironmentVariables.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.DotNet.HotReload; + +internal static class AgentEnvironmentVariables +{ + /// + /// Intentionally different from the variable name used by the debugger. + /// This is to avoid the debugger colliding with dotnet-watch pipe connection when debugging dotnet-watch (or tests). + /// + public const string DotNetWatchHotReloadNamedPipeName = "DOTNET_WATCH_HOTRELOAD_NAMEDPIPE_NAME"; + + /// + /// The full path to the process being launched by dotnet run. + /// Workaround for https://github.com/dotnet/sdk/issues/40484 + /// + public const string DotNetWatchHotReloadTargetProcessPath = "DOTNET_WATCH_HOTRELOAD_TARGET_PROCESS_PATH"; + + /// + /// Enables logging from the client delta applier agent. + /// + public const string HotReloadDeltaClientLogMessages = "HOTRELOAD_DELTA_CLIENT_LOG_MESSAGES"; + + /// + /// dotnet runtime environment variable. + /// https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-environment-variables#dotnet_startup_hooks + /// + public const string DotNetStartupHooks = "DOTNET_STARTUP_HOOKS"; + + /// + /// dotnet runtime environment variable. + /// + public const string DotNetModifiableAssemblies = "DOTNET_MODIFIABLE_ASSEMBLIES"; +} diff --git a/src/BuiltInTools/HotReloadAgent/HotReloadAgent.cs b/src/BuiltInTools/HotReloadAgent/HotReloadAgent.cs index 7e1f026d8faa..f88d44707ce3 100644 --- a/src/BuiltInTools/HotReloadAgent/HotReloadAgent.cs +++ b/src/BuiltInTools/HotReloadAgent/HotReloadAgent.cs @@ -2,12 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Linq; -using System.Collections.Generic; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Diagnostics; +using System.IO; +using System.Linq; using System.Reflection; -using Microsoft.DotNet.Watch; namespace Microsoft.DotNet.HotReload; @@ -127,7 +127,9 @@ public void ApplyDeltas(IEnumerable deltas) cachedDeltas.Add(delta); } - _metadataUpdateHandlerInvoker.Invoke(GetMetadataUpdateTypes(deltas)); + _metadataUpdateHandlerInvoker.MetadataUpdated(GetMetadataUpdateTypes(deltas)); + + Reporter.Report("Deltas applied.", AgentMessageSeverity.Verbose); } private Type[] GetMetadataUpdateTypes(IEnumerable deltas) @@ -196,4 +198,42 @@ private void ApplyDeltas(Assembly assembly, IReadOnlyList deltas) return default; } + + /// + /// Applies the content update. + /// + public void ApplyStaticAssetUpdate(StaticAssetUpdate update) + { + _metadataUpdateHandlerInvoker.ContentUpdated(update); + } + + /// + /// Clear any hot-reload specific environment variables. This prevents child processes from being + /// affected by the current app's hot reload settings. See https://github.com/dotnet/runtime/issues/58000 + /// + public static void ClearHotReloadEnvironmentVariables(Type startupHookType) + { + Environment.SetEnvironmentVariable(AgentEnvironmentVariables.DotNetStartupHooks, + RemoveCurrentAssembly(startupHookType, Environment.GetEnvironmentVariable(AgentEnvironmentVariables.DotNetStartupHooks)!)); + + Environment.SetEnvironmentVariable(AgentEnvironmentVariables.DotNetWatchHotReloadNamedPipeName, ""); + Environment.SetEnvironmentVariable(AgentEnvironmentVariables.HotReloadDeltaClientLogMessages, ""); + } + + // internal for testing + internal static string RemoveCurrentAssembly(Type startupHookType, string environment) + { + if (environment is "") + { + return environment; + } + + var comparison = Path.DirectorySeparatorChar == '\\' ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; + + var assemblyLocation = startupHookType.Assembly.Location; + var updatedValues = environment.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries) + .Where(e => !string.Equals(e, assemblyLocation, comparison)); + + return string.Join(Path.PathSeparator, updatedValues); + } } diff --git a/src/BuiltInTools/HotReloadAgent/MetadataUpdateHandlerInvoker.cs b/src/BuiltInTools/HotReloadAgent/MetadataUpdateHandlerInvoker.cs index fa8b0630e840..5924d9fbc3ad 100644 --- a/src/BuiltInTools/HotReloadAgent/MetadataUpdateHandlerInvoker.cs +++ b/src/BuiltInTools/HotReloadAgent/MetadataUpdateHandlerInvoker.cs @@ -6,6 +6,7 @@ using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Threading; +using System.Runtime.CompilerServices; namespace Microsoft.DotNet.HotReload; @@ -18,34 +19,71 @@ namespace Microsoft.DotNet.HotReload; #endif internal sealed class MetadataUpdateHandlerInvoker(AgentReporter reporter) { - internal sealed class RegisteredActions(IReadOnlyList> clearCache, IReadOnlyList> updateApplication) + internal delegate void ContentUpdateAction(StaticAssetUpdate update); + internal delegate void MetadataUpdateAction(Type[]? updatedTypes); + + internal readonly struct UpdateHandler(TAction action, MethodInfo method) + where TAction : Delegate + { + public TAction Action { get; } = action; + public MethodInfo Method { get; } = method; + + public void ReportInvocation(AgentReporter reporter) + => reporter.Report(GetHandlerDisplayString(Method), AgentMessageSeverity.Verbose); + } + + internal sealed class RegisteredActions( + IReadOnlyList> clearCacheHandlers, + IReadOnlyList> updateApplicationHandlers, + List> updateContentHandlers) { - public void Invoke(Type[] updatedTypes) + public void MetadataUpdated(AgentReporter reporter, Type[] updatedTypes) { - foreach (var action in clearCache) + foreach (var handler in clearCacheHandlers) { - action(updatedTypes); + handler.ReportInvocation(reporter); + handler.Action(updatedTypes); } - foreach (var action in updateApplication) + foreach (var handler in updateApplicationHandlers) { - action(updatedTypes); + handler.ReportInvocation(reporter); + handler.Action(updatedTypes); } } + public void UpdateContent(AgentReporter reporter, StaticAssetUpdate update) + { + foreach (var handler in updateContentHandlers) + { + handler.ReportInvocation(reporter); + handler.Action(update); + } + } + + /// + /// For testing. + /// + internal IEnumerable> ClearCacheHandlers => clearCacheHandlers; + /// /// For testing. /// - internal IEnumerable> ClearCache => clearCache; + internal IEnumerable> UpdateApplicationHandlers => updateApplicationHandlers; /// /// For testing. /// - internal IEnumerable> UpdateApplication => updateApplication; + internal IEnumerable> UpdateContentHandlers => updateContentHandlers; } private const string ClearCacheHandlerName = "ClearCache"; private const string UpdateApplicationHandlerName = "UpdateApplication"; + private const string UpdateContentHandlerName = "UpdateContent"; + private const BindingFlags HandlerMethodBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static; + + private static readonly Type[] s_contentUpdateSignature = [typeof(string), typeof(bool), typeof(string), typeof(byte[])]; + private static readonly Type[] s_metadataUpdateSignature = [typeof(Type[])]; private RegisteredActions? _actions; @@ -55,27 +93,47 @@ public void Invoke(Type[] updatedTypes) internal void Clear() => Interlocked.Exchange(ref _actions, null); + private RegisteredActions GetActions() + { + // Defer discovering metadata updata handlers until after hot reload deltas have been applied. + // This should give enough opportunity for AppDomain.GetAssemblies() to be sufficiently populated. + var actions = _actions; + if (actions == null) + { + Interlocked.CompareExchange(ref _actions, GetUpdateHandlerActions(), null); + actions = _actions; + } + + return actions; + } + /// - /// Invokes all registerd handlers. + /// Invokes all registered mtadata update handlers. /// - internal void Invoke(Type[] updatedTypes) + internal void MetadataUpdated(Type[] updatedTypes) { try { - // Defer discovering metadata updata handlers until after hot reload deltas have been applied. - // This should give enough opportunity for AppDomain.GetAssemblies() to be sufficiently populated. - var actions = _actions; - if (actions == null) - { - Interlocked.CompareExchange(ref _actions, GetMetadataUpdateHandlerActions(), null); - actions = _actions; - } - reporter.Report("Invoking metadata update handlers.", AgentMessageSeverity.Verbose); - actions.Invoke(updatedTypes); + GetActions().MetadataUpdated(reporter, updatedTypes); + } + catch (Exception e) + { + reporter.Report(e.ToString(), AgentMessageSeverity.Warning); + } + } + + /// + /// Invokes all registered content update handlers. + /// + internal void ContentUpdated(StaticAssetUpdate update) + { + try + { + reporter.Report("Invoking content update handlers.", AgentMessageSeverity.Verbose); - reporter.Report("Deltas applied.", AgentMessageSeverity.Verbose); + GetActions().UpdateContent(reporter, update); } catch (Exception e) { @@ -116,67 +174,111 @@ private IEnumerable GetHandlerTypes() } } - public RegisteredActions GetMetadataUpdateHandlerActions() - => GetMetadataUpdateHandlerActions(GetHandlerTypes()); + public RegisteredActions GetUpdateHandlerActions() + => GetUpdateHandlerActions(GetHandlerTypes()); /// /// Internal for testing. /// - internal RegisteredActions GetMetadataUpdateHandlerActions(IEnumerable handlerTypes) + internal RegisteredActions GetUpdateHandlerActions(IEnumerable handlerTypes) { - var clearCacheActions = new List>(); - var updateApplicationActions = new List>(); + var clearCacheHandlers = new List>(); + var applicationUpdateHandlers = new List>(); + var contentUpdateHandlers = new List>(); foreach (var handlerType in handlerTypes) { bool methodFound = false; - if (GetUpdateMethod(handlerType, ClearCacheHandlerName) is MethodInfo clearCache) + if (GetMetadataUpdateMethod(handlerType, ClearCacheHandlerName) is MethodInfo clearCache) { - clearCacheActions.Add(CreateAction(clearCache)); + clearCacheHandlers.Add(CreateMetadataUpdateAction(clearCache)); methodFound = true; } - if (GetUpdateMethod(handlerType, UpdateApplicationHandlerName) is MethodInfo updateApplication) + if (GetMetadataUpdateMethod(handlerType, UpdateApplicationHandlerName) is MethodInfo updateApplication) { - updateApplicationActions.Add(CreateAction(updateApplication)); + applicationUpdateHandlers.Add(CreateMetadataUpdateAction(updateApplication)); + methodFound = true; + } + + if (GetContentUpdateMethod(handlerType, UpdateContentHandlerName) is MethodInfo updateContent) + { + contentUpdateHandlers.Add(CreateContentUpdateAction(updateContent)); methodFound = true; } if (!methodFound) { reporter.Report( - $"Expected to find a static method '{ClearCacheHandlerName}' or '{UpdateApplicationHandlerName}' on type '{handlerType.AssemblyQualifiedName}' but neither exists.", + $"Expected to find a static method '{ClearCacheHandlerName}', '{UpdateApplicationHandlerName}' or '{UpdateContentHandlerName}' on type '{handlerType.AssemblyQualifiedName}' but neither exists.", AgentMessageSeverity.Warning); } } - return new RegisteredActions(clearCacheActions, updateApplicationActions); + return new RegisteredActions(clearCacheHandlers, applicationUpdateHandlers, contentUpdateHandlers); - Action CreateAction(MethodInfo update) + UpdateHandler CreateMetadataUpdateAction(MethodInfo method) { - var action = (Action)update.CreateDelegate(typeof(Action)); - return types => + var action = (MetadataUpdateAction)method.CreateDelegate(typeof(MetadataUpdateAction)); + return new(types => { try { action(types); } - catch (Exception ex) + catch (Exception e) { - reporter.Report($"Exception from '{action}': {ex}", AgentMessageSeverity.Warning); + ReportException(e, method); } - }; + }, method); } - MethodInfo? GetUpdateMethod(Type handlerType, string name) + UpdateHandler CreateContentUpdateAction(MethodInfo method) + { + var action = (Action)method.CreateDelegate(typeof(Action)); + return new(update => + { + try + { + action(update.AssemblyName, update.IsApplicationProject, update.RelativePath, update.Contents); + } + catch (Exception e) + { + ReportException(e, method); + } + }, method); + } + + void ReportException(Exception e, MethodInfo method) + => reporter.Report($"Exception from '{GetHandlerDisplayString(method)}': {e}", AgentMessageSeverity.Warning); + + MethodInfo? GetMetadataUpdateMethod(Type handlerType, string name) { - if (handlerType.GetMethod(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static, binder: null, [typeof(Type[])], modifiers: null) is MethodInfo updateMethod && + if (handlerType.GetMethod(name, HandlerMethodBindingFlags, binder: null, s_metadataUpdateSignature, modifiers: null) is MethodInfo updateMethod && updateMethod.ReturnType == typeof(void)) { return updateMethod; } + ReportSignatureMismatch(handlerType, name); + return null; + } + + MethodInfo? GetContentUpdateMethod(Type handlerType, string name) + { + if (handlerType.GetMethod(name, HandlerMethodBindingFlags, binder: null, s_contentUpdateSignature, modifiers: null) is MethodInfo updateMethod && + updateMethod.ReturnType == typeof(void)) + { + return updateMethod; + } + + ReportSignatureMismatch(handlerType, name); + return null; + } + + void ReportSignatureMismatch(Type handlerType, string name) + { foreach (MethodInfo method in handlerType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)) { if (method.Name == name) @@ -185,11 +287,12 @@ internal RegisteredActions GetMetadataUpdateHandlerActions(IEnumerable han break; } } - - return null; } } + private static string GetHandlerDisplayString(MethodInfo method) + => $"{method.DeclaringType!.FullName}.{method.Name}"; + private IList TryGetCustomAttributesData(Assembly assembly) { try diff --git a/src/BuiltInTools/HotReloadAgent/StaticAssetUpdate.cs b/src/BuiltInTools/HotReloadAgent/StaticAssetUpdate.cs new file mode 100644 index 000000000000..3601980b93ee --- /dev/null +++ b/src/BuiltInTools/HotReloadAgent/StaticAssetUpdate.cs @@ -0,0 +1,13 @@ +namespace Microsoft.DotNet.HotReload; + +internal readonly struct StaticAssetUpdate( + string assemblyName, + string relativePath, + byte[] contents, + bool isApplicationProject) +{ + public string AssemblyName { get; } = assemblyName; + public bool IsApplicationProject { get; } = isApplicationProject; + public string RelativePath { get; } = relativePath; + public byte[] Contents { get; } = contents; +} diff --git a/src/BuiltInTools/HotReloadAgent/UpdateDelta.cs b/src/BuiltInTools/HotReloadAgent/UpdateDelta.cs index 3277755dea56..757e46c28ee4 100644 --- a/src/BuiltInTools/HotReloadAgent/UpdateDelta.cs +++ b/src/BuiltInTools/HotReloadAgent/UpdateDelta.cs @@ -3,7 +3,7 @@ using System; -namespace Microsoft.DotNet.Watch; +namespace Microsoft.DotNet.HotReload; internal readonly struct UpdateDelta(Guid moduleId, byte[] metadataDelta, byte[] ilDelta, byte[] pdbDelta, int[] updatedTypes) { diff --git a/src/BuiltInTools/dotnet-format/Commands/FormatAnalyzersCommand.cs b/src/BuiltInTools/dotnet-format/Commands/FormatAnalyzersCommand.cs index 3a601096addf..1fc765d41cf5 100644 --- a/src/BuiltInTools/dotnet-format/Commands/FormatAnalyzersCommand.cs +++ b/src/BuiltInTools/dotnet-format/Commands/FormatAnalyzersCommand.cs @@ -3,7 +3,6 @@ using System.Collections.Immutable; using System.CommandLine; using System.CommandLine.Invocation; -using System.CommandLine.IO; using Microsoft.Extensions.Logging; using static Microsoft.CodeAnalysis.Tools.FormatCommandCommon; @@ -31,7 +30,7 @@ private class FormatAnalyzersHandler : AsynchronousCliAction public override async Task InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken) { var formatOptions = parseResult.ParseVerbosityOption(FormatOptions.Instance); - var logger = new SystemConsole().SetupLogging(minimalLogLevel: formatOptions.LogLevel, minimalErrorLevel: LogLevel.Warning); + var logger = SetupLogging(minimalLogLevel: formatOptions.LogLevel, minimalErrorLevel: LogLevel.Warning); formatOptions = parseResult.ParseCommonOptions(formatOptions, logger); formatOptions = parseResult.ParseWorkspaceOptions(formatOptions); diff --git a/src/BuiltInTools/dotnet-format/Commands/FormatCommandCommon.cs b/src/BuiltInTools/dotnet-format/Commands/FormatCommandCommon.cs index a801de15dfbf..48acb26267d4 100644 --- a/src/BuiltInTools/dotnet-format/Commands/FormatCommandCommon.cs +++ b/src/BuiltInTools/dotnet-format/Commands/FormatCommandCommon.cs @@ -137,10 +137,10 @@ public static CliArgument DefaultToCurrentDirectory(this CliArgument SetupLogging(this IConsole console, LogLevel minimalLogLevel, LogLevel minimalErrorLevel) + public static ILogger SetupLogging(LogLevel minimalLogLevel, LogLevel minimalErrorLevel) { var loggerFactory = new LoggerFactory() - .AddSimpleConsole(console, minimalLogLevel, minimalErrorLevel); + .AddSimpleConsole(minimalLogLevel, minimalErrorLevel); var logger = loggerFactory.CreateLogger(); return logger; } diff --git a/src/BuiltInTools/dotnet-format/Commands/FormatStyleCommand.cs b/src/BuiltInTools/dotnet-format/Commands/FormatStyleCommand.cs index d7aaa6519774..12d96959c6bc 100644 --- a/src/BuiltInTools/dotnet-format/Commands/FormatStyleCommand.cs +++ b/src/BuiltInTools/dotnet-format/Commands/FormatStyleCommand.cs @@ -3,7 +3,6 @@ using System.Collections.Immutable; using System.CommandLine; using System.CommandLine.Invocation; -using System.CommandLine.IO; using Microsoft.Extensions.Logging; using static Microsoft.CodeAnalysis.Tools.FormatCommandCommon; @@ -31,7 +30,7 @@ private class FormatStyleHandler : AsynchronousCliAction public override async Task InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken) { var formatOptions = parseResult.ParseVerbosityOption(FormatOptions.Instance); - var logger = new SystemConsole().SetupLogging(minimalLogLevel: formatOptions.LogLevel, minimalErrorLevel: LogLevel.Warning); + var logger = SetupLogging(minimalLogLevel: formatOptions.LogLevel, minimalErrorLevel: LogLevel.Warning); formatOptions = parseResult.ParseCommonOptions(formatOptions, logger); formatOptions = parseResult.ParseWorkspaceOptions(formatOptions); diff --git a/src/BuiltInTools/dotnet-format/Commands/FormatWhitespaceCommand.cs b/src/BuiltInTools/dotnet-format/Commands/FormatWhitespaceCommand.cs index 3c28fe4c5474..0885f96f284d 100644 --- a/src/BuiltInTools/dotnet-format/Commands/FormatWhitespaceCommand.cs +++ b/src/BuiltInTools/dotnet-format/Commands/FormatWhitespaceCommand.cs @@ -2,7 +2,6 @@ using System.CommandLine; using System.CommandLine.Invocation; -using System.CommandLine.IO; using System.CommandLine.Parsing; using Microsoft.Extensions.Logging; using static Microsoft.CodeAnalysis.Tools.FormatCommandCommon; @@ -11,21 +10,6 @@ namespace Microsoft.CodeAnalysis.Tools.Commands { internal static class FormatWhitespaceCommand { - // This delegate should be kept in Sync with the FormatCommand options and argument names - // so that values bind correctly. - internal delegate Task Handler( - bool folder, - string? workspace, - bool noRestore, - bool check, - string[] include, - string[] exclude, - bool includeGenerated, - string? verbosity, - string? binarylog, - string? report, - IConsole console); - private static readonly FormatWhitespaceHandler s_formattingHandler = new(); internal static CliCommand GetCommand() @@ -66,7 +50,7 @@ private class FormatWhitespaceHandler : AsynchronousCliAction public override async Task InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken) { var formatOptions = parseResult.ParseVerbosityOption(FormatOptions.Instance); - var logger = new SystemConsole().SetupLogging(minimalLogLevel: formatOptions.LogLevel, minimalErrorLevel: LogLevel.Warning); + var logger = SetupLogging(minimalLogLevel: formatOptions.LogLevel, minimalErrorLevel: LogLevel.Warning); formatOptions = parseResult.ParseCommonOptions(formatOptions, logger); formatOptions = parseResult.ParseWorkspaceOptions(formatOptions); diff --git a/src/BuiltInTools/dotnet-format/Commands/RootFormatCommand.cs b/src/BuiltInTools/dotnet-format/Commands/RootFormatCommand.cs index 55947beed4ad..66d036f85c2b 100644 --- a/src/BuiltInTools/dotnet-format/Commands/RootFormatCommand.cs +++ b/src/BuiltInTools/dotnet-format/Commands/RootFormatCommand.cs @@ -3,7 +3,6 @@ using System.Collections.Immutable; using System.CommandLine; using System.CommandLine.Invocation; -using System.CommandLine.IO; using Microsoft.Extensions.Logging; using static Microsoft.CodeAnalysis.Tools.FormatCommandCommon; @@ -34,7 +33,7 @@ private class FormatCommandDefaultHandler : AsynchronousCliAction public override async Task InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken) { var formatOptions = parseResult.ParseVerbosityOption(FormatOptions.Instance); - var logger = new SystemConsole().SetupLogging(minimalLogLevel: formatOptions.LogLevel, minimalErrorLevel: LogLevel.Warning); + var logger = SetupLogging(minimalLogLevel: formatOptions.LogLevel, minimalErrorLevel: LogLevel.Warning); formatOptions = parseResult.ParseCommonOptions(formatOptions, logger); formatOptions = parseResult.ParseWorkspaceOptions(formatOptions); diff --git a/src/BuiltInTools/dotnet-format/Logging/SimpleConsoleLogger.cs b/src/BuiltInTools/dotnet-format/Logging/SimpleConsoleLogger.cs index 6c25bfbb85c6..966818d2f16e 100644 --- a/src/BuiltInTools/dotnet-format/Logging/SimpleConsoleLogger.cs +++ b/src/BuiltInTools/dotnet-format/Logging/SimpleConsoleLogger.cs @@ -1,18 +1,18 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. using System.Collections.Immutable; -using System.CommandLine; -using System.CommandLine.Rendering; using Microsoft.Extensions.Logging; namespace Microsoft.CodeAnalysis.Tools.Logging { internal class SimpleConsoleLogger : ILogger { - private readonly object _gate = new object(); + private static readonly bool ColorsAreSupported = + !(OperatingSystem.IsBrowser() || OperatingSystem.IsAndroid() || OperatingSystem.IsIOS() || OperatingSystem.IsTvOS()) + && !Console.IsOutputRedirected; + + private readonly static object _gate = new object(); - private readonly IConsole _console; - private readonly ITerminal _terminal; private readonly LogLevel _minimalLogLevel; private readonly LogLevel _minimalErrorLevel; @@ -27,10 +27,8 @@ internal class SimpleConsoleLogger : ILogger [LogLevel.None] = ConsoleColor.White, }.ToImmutableDictionary(); - public SimpleConsoleLogger(IConsole console, LogLevel minimalLogLevel, LogLevel minimalErrorLevel) + public SimpleConsoleLogger(LogLevel minimalLogLevel, LogLevel minimalErrorLevel) { - _terminal = console.GetTerminal(); - _console = console; _minimalLogLevel = minimalLogLevel; _minimalErrorLevel = minimalErrorLevel; } @@ -46,14 +44,8 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except { var message = formatter(state, exception); var logToErrorStream = logLevel >= _minimalErrorLevel; - if (_terminal is null) - { - LogToConsole(_console, message, logToErrorStream); - } - else - { - LogToTerminal(message, logLevel, logToErrorStream); - } + + Log(message, logLevel, logToErrorStream); } } @@ -67,25 +59,25 @@ public bool IsEnabled(LogLevel logLevel) return NullScope.Instance; } - private void LogToTerminal(string message, LogLevel logLevel, bool logToErrorStream) + private void Log(string message, LogLevel logLevel, bool logToErrorStream) { - var messageColor = LogLevelColorMap[logLevel]; - _terminal.ForegroundColor = messageColor; - - LogToConsole(_terminal, message, logToErrorStream); - - _terminal.ResetColor(); - } + if (ColorsAreSupported) + { + Console.ForegroundColor = LogLevelColorMap[logLevel]; + } - private static void LogToConsole(IConsole console, string message, bool logToErrorStream) - { if (logToErrorStream) { - console.Error.Write($"{message}{Environment.NewLine}"); + Console.Error.WriteLine(message); } else { - console.Out.Write($" {message}{Environment.NewLine}"); + Console.Out.WriteLine(message); + } + + if (ColorsAreSupported) + { + Console.ResetColor(); } } } diff --git a/src/BuiltInTools/dotnet-format/Logging/SimpleConsoleLoggerFactoryExtensions.cs b/src/BuiltInTools/dotnet-format/Logging/SimpleConsoleLoggerFactoryExtensions.cs index 5795b9e3bd7d..cc9dd09e69c4 100644 --- a/src/BuiltInTools/dotnet-format/Logging/SimpleConsoleLoggerFactoryExtensions.cs +++ b/src/BuiltInTools/dotnet-format/Logging/SimpleConsoleLoggerFactoryExtensions.cs @@ -1,15 +1,14 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. -using System.CommandLine; using Microsoft.Extensions.Logging; namespace Microsoft.CodeAnalysis.Tools.Logging { internal static class SimpleConsoleLoggerFactoryExtensions { - public static ILoggerFactory AddSimpleConsole(this ILoggerFactory factory, IConsole console, LogLevel minimalLogLevel, LogLevel minimalErrorLevel) + public static ILoggerFactory AddSimpleConsole(this ILoggerFactory factory, LogLevel minimalLogLevel, LogLevel minimalErrorLevel) { - factory.AddProvider(new SimpleConsoleLoggerProvider(console, minimalLogLevel, minimalErrorLevel)); + factory.AddProvider(new SimpleConsoleLoggerProvider(minimalLogLevel, minimalErrorLevel)); return factory; } } diff --git a/src/BuiltInTools/dotnet-format/Logging/SimpleConsoleLoggerProvider.cs b/src/BuiltInTools/dotnet-format/Logging/SimpleConsoleLoggerProvider.cs index 1b98c212df40..7674c8a5d3a1 100644 --- a/src/BuiltInTools/dotnet-format/Logging/SimpleConsoleLoggerProvider.cs +++ b/src/BuiltInTools/dotnet-format/Logging/SimpleConsoleLoggerProvider.cs @@ -1,26 +1,23 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. -using System.CommandLine; using Microsoft.Extensions.Logging; namespace Microsoft.CodeAnalysis.Tools.Logging { internal class SimpleConsoleLoggerProvider : ILoggerProvider { - private readonly IConsole _console; private readonly LogLevel _minimalLogLevel; private readonly LogLevel _minimalErrorLevel; - public SimpleConsoleLoggerProvider(IConsole console, LogLevel minimalLogLevel, LogLevel minimalErrorLevel) + public SimpleConsoleLoggerProvider(LogLevel minimalLogLevel, LogLevel minimalErrorLevel) { - _console = console; _minimalLogLevel = minimalLogLevel; _minimalErrorLevel = minimalErrorLevel; } public ILogger CreateLogger(string name) { - return new SimpleConsoleLogger(_console, _minimalLogLevel, _minimalErrorLevel); + return new SimpleConsoleLogger(_minimalLogLevel, _minimalErrorLevel); } public void Dispose() diff --git a/src/BuiltInTools/dotnet-format/Workspaces/MSBuildWorkspaceFinder.cs b/src/BuiltInTools/dotnet-format/Workspaces/MSBuildWorkspaceFinder.cs index f654dade542c..4bdc9001568a 100644 --- a/src/BuiltInTools/dotnet-format/Workspaces/MSBuildWorkspaceFinder.cs +++ b/src/BuiltInTools/dotnet-format/Workspaces/MSBuildWorkspaceFinder.cs @@ -76,8 +76,11 @@ private static (bool isSolution, string workspacePath) FindFile(string workspace return (isSolution, workspacePath); } - private static IEnumerable FindSolutionFiles(string basePath) => Directory.EnumerateFileSystemEntries(basePath, "*.sln", SearchOption.TopDirectoryOnly) - .Concat(Directory.EnumerateFileSystemEntries(basePath, "*.slnf", SearchOption.TopDirectoryOnly)); + private static IEnumerable FindSolutionFiles(string basePath) => [ + ..Directory.EnumerateFileSystemEntries(basePath, "*.sln", SearchOption.TopDirectoryOnly), + ..Directory.EnumerateFileSystemEntries(basePath, "*.slnf", SearchOption.TopDirectoryOnly), + ..Directory.EnumerateFileSystemEntries(basePath, "*.slnx", SearchOption.TopDirectoryOnly) + ]; private static IEnumerable FindProjectFiles(string basePath) => Directory.EnumerateFileSystemEntries(basePath, "*.*proj", SearchOption.TopDirectoryOnly) .Where(f => !DnxProjectExtension.Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase)); diff --git a/src/BuiltInTools/dotnet-format/dotnet-format.csproj b/src/BuiltInTools/dotnet-format/dotnet-format.csproj index dda1c67a29db..dd60e3a0f784 100644 --- a/src/BuiltInTools/dotnet-format/dotnet-format.csproj +++ b/src/BuiltInTools/dotnet-format/dotnet-format.csproj @@ -49,7 +49,6 @@ - diff --git a/src/BuiltInTools/dotnet-watch.slnf b/src/BuiltInTools/dotnet-watch.slnf index 2484e98c2da7..b0e0ee2dcafc 100644 --- a/src/BuiltInTools/dotnet-watch.slnf +++ b/src/BuiltInTools/dotnet-watch.slnf @@ -9,6 +9,8 @@ "src\\BuiltInTools\\DotNetWatchTasks\\DotNetWatchTasks.csproj", "src\\BuiltInTools\\HotReloadAgent\\Microsoft.DotNet.HotReload.Agent.Package.csproj", "src\\BuiltInTools\\HotReloadAgent\\Microsoft.DotNet.HotReload.Agent.shproj", + "src\\BuiltInTools\\HotReloadAgent.PipeRpc\\Microsoft.DotNet.HotReload.Agent.PipeRpc.Package.csproj", + "src\\BuiltInTools\\HotReloadAgent.PipeRpc\\Microsoft.DotNet.HotReload.Agent.PipeRpc.shproj", "src\\BuiltInTools\\dotnet-watch\\dotnet-watch.csproj", "test\\Microsoft.AspNetCore.Watch.BrowserRefresh.Tests\\Microsoft.AspNetCore.Watch.BrowserRefresh.Tests.csproj", "test\\Microsoft.Extensions.DotNetDeltaApplier.Tests\\Microsoft.Extensions.DotNetDeltaApplier.Tests.csproj", diff --git a/src/BuiltInTools/dotnet-watch/Aspire/AspireServiceFactory.cs b/src/BuiltInTools/dotnet-watch/Aspire/AspireServiceFactory.cs index d806dd11ba45..158a49274bf6 100644 --- a/src/BuiltInTools/dotnet-watch/Aspire/AspireServiceFactory.cs +++ b/src/BuiltInTools/dotnet-watch/Aspire/AspireServiceFactory.cs @@ -12,7 +12,7 @@ namespace Microsoft.DotNet.Watch; internal class AspireServiceFactory : IRuntimeProcessLauncherFactory { - private sealed class SessionManager : IAspireServerEvents, IRuntimeProcessLauncher + internal sealed class SessionManager : IAspireServerEvents, IRuntimeProcessLauncher { private readonly struct Session(string dcpId, string sessionId, RunningProject runningProject, Task outputReader) { @@ -30,7 +30,7 @@ private readonly struct Session(string dcpId, string sessionId, RunningProject r private readonly ProjectLauncher _projectLauncher; private readonly AspireServerService _service; - private readonly IReadOnlyList _buildArguments; + private readonly ProjectOptions _hostProjectOptions; /// /// Lock to access: @@ -43,10 +43,10 @@ private readonly struct Session(string dcpId, string sessionId, RunningProject r private int _sessionIdDispenser; private volatile bool _isDisposed; - public SessionManager(ProjectLauncher projectLauncher, IReadOnlyList buildArguments) + public SessionManager(ProjectLauncher projectLauncher, ProjectOptions hostProjectOptions) { _projectLauncher = projectLauncher; - _buildArguments = buildArguments; + _hostProjectOptions = hostProjectOptions; _service = new AspireServerService( this, @@ -204,44 +204,64 @@ private async ValueTask TerminateSessionAsync(Session session, CancellationToken } private ProjectOptions GetProjectOptions(ProjectLaunchRequest projectLaunchInfo) + { + var hostLaunchProfile = _hostProjectOptions.NoLaunchProfile ? null : _hostProjectOptions.LaunchProfileName; + + return new() + { + IsRootProject = false, + ProjectPath = projectLaunchInfo.ProjectPath, + WorkingDirectory = _projectLauncher.EnvironmentOptions.WorkingDirectory, + BuildArguments = _hostProjectOptions.BuildArguments, + Command = "run", + CommandArguments = GetRunCommandArguments(projectLaunchInfo, hostLaunchProfile), + LaunchEnvironmentVariables = projectLaunchInfo.Environment?.Select(e => (e.Key, e.Value))?.ToArray() ?? [], + LaunchProfileName = projectLaunchInfo.LaunchProfile, + NoLaunchProfile = projectLaunchInfo.DisableLaunchProfile, + TargetFramework = _hostProjectOptions.TargetFramework, + }; + } + + // internal for testing + internal static IReadOnlyList GetRunCommandArguments(ProjectLaunchRequest projectLaunchInfo, string? hostLaunchProfile) { var arguments = new List { "--project", projectLaunchInfo.ProjectPath, - // TODO: https://github.com/dotnet/sdk/issues/43946 - // Need to suppress launch profile for now, otherwise it would override the port set via env variable. - "--no-launch-profile", }; - //if (projectLaunchInfo.DisableLaunchProfile) - //{ - // arguments.Add("--no-launch-profile"); - //} - //else if (!string.IsNullOrEmpty(projectLaunchInfo.LaunchProfile)) - //{ - // arguments.Add("--launch-profile"); - // arguments.Add(projectLaunchInfo.LaunchProfile); - //} + // Implements https://github.com/dotnet/aspire/blob/main/docs/specs/IDE-execution.md#launch-profile-processing-project-launch-configuration - if (projectLaunchInfo.Arguments != null) + if (projectLaunchInfo.DisableLaunchProfile) + { + arguments.Add("--no-launch-profile"); + } + else if (!string.IsNullOrEmpty(projectLaunchInfo.LaunchProfile)) { - arguments.AddRange(projectLaunchInfo.Arguments); + arguments.Add("--launch-profile"); + arguments.Add(projectLaunchInfo.LaunchProfile); + } + else if (hostLaunchProfile != null) + { + arguments.Add("--launch-profile"); + arguments.Add(hostLaunchProfile); } - return new() + if (projectLaunchInfo.Arguments != null) { - IsRootProject = false, - ProjectPath = projectLaunchInfo.ProjectPath, - WorkingDirectory = _projectLauncher.EnvironmentOptions.WorkingDirectory, // TODO: Should DCP protocol specify? - BuildArguments = _buildArguments, // TODO: Should DCP protocol specify? - Command = "run", - CommandArguments = arguments, - LaunchEnvironmentVariables = projectLaunchInfo.Environment?.Select(kvp => (kvp.Key, kvp.Value)).ToArray() ?? [], - LaunchProfileName = projectLaunchInfo.LaunchProfile, - NoLaunchProfile = projectLaunchInfo.DisableLaunchProfile, - TargetFramework = null, // TODO: Should DCP protocol specify? - }; + if (projectLaunchInfo.Arguments.Any()) + { + arguments.AddRange(projectLaunchInfo.Arguments); + } + else + { + // indicate that no arguments should be used even if launch profile specifies some: + arguments.Add("--no-launch-profile-arguments"); + } + } + + return arguments; } } @@ -250,8 +270,8 @@ private ProjectOptions GetProjectOptions(ProjectLaunchRequest projectLaunchInfo) public static readonly AspireServiceFactory Instance = new(); public const string AppHostProjectCapability = "Aspire"; - public IRuntimeProcessLauncher? TryCreate(ProjectGraphNode projectNode, ProjectLauncher projectLauncher, IReadOnlyList buildArguments) + public IRuntimeProcessLauncher? TryCreate(ProjectGraphNode projectNode, ProjectLauncher projectLauncher, ProjectOptions hostProjectOptions) => projectNode.GetCapabilities().Contains(AppHostProjectCapability) - ? new SessionManager(projectLauncher, buildArguments) + ? new SessionManager(projectLauncher, hostProjectOptions) : null; } diff --git a/src/BuiltInTools/dotnet-watch/Browser/BrowserConnector.cs b/src/BuiltInTools/dotnet-watch/Browser/BrowserConnector.cs index 9126b8ec54b6..733a7abec5c5 100644 --- a/src/BuiltInTools/dotnet-watch/Browser/BrowserConnector.cs +++ b/src/BuiltInTools/dotnet-watch/Browser/BrowserConnector.cs @@ -9,15 +9,19 @@ namespace Microsoft.DotNet.Watch { - internal sealed partial class BrowserConnector(DotNetWatchContext context) : IAsyncDisposable + internal sealed partial class BrowserConnector(DotNetWatchContext context) : IAsyncDisposable, IStaticAssetChangeApplierProvider { // This needs to be in sync with the version BrowserRefreshMiddleware is compiled against. private static readonly Version s_minimumSupportedVersion = Versions.Version6_0; - private static readonly Regex s_nowListeningRegex = s_nowListeningOnRegex(); + private static readonly Regex s_nowListeningRegex = GetNowListeningOnRegex(); + private static readonly Regex s_aspireDashboardUrlRegex = GetAspireDashboardUrlRegex(); [GeneratedRegex(@"Now listening on: (?.*)\s*$", RegexOptions.Compiled)] - private static partial Regex s_nowListeningOnRegex(); + private static partial Regex GetNowListeningOnRegex(); + + [GeneratedRegex(@"Login to the dashboard at (?.*)\s*$", RegexOptions.Compiled)] + private static partial Regex GetAspireDashboardUrlRegex(); private readonly object _serversGuard = new(); private readonly Dictionary _servers = []; @@ -44,7 +48,12 @@ await Task.WhenAll(serversToDispose.Select(async server => })); } - public async ValueTask LaunchOrRefreshBrowserAsync( + /// + /// A single browser refresh server is created for each project that supports browser launching. + /// When the project is rebuilt we reuse the same refresh server and browser instance. + /// Reload message is sent to the browser in that case. + /// + public async ValueTask GetOrCreateBrowserRefreshServerAsync( ProjectGraphNode projectNode, ProcessSpec processSpec, EnvironmentVariablesBuilder environmentBuilder, @@ -64,12 +73,9 @@ await Task.WhenAll(serversToDispose.Select(async server => } } - // Attach trigger to the process that launches browser on URL found in the process output. - // Only do so for root projects, not for child processes. - if (projectOptions.IsRootProject) - { - processSpec.OnOutput += GetBrowserLaunchTrigger(projectNode, projectOptions, server, cancellationToken); - } + // Attach trigger to the process that detects when the web server reports to the output that it's listening. + // Launches browser on the URL found in the process output for root projects. + processSpec.OnOutput += GetBrowserLaunchTrigger(projectNode, projectOptions, server, cancellationToken); if (server == null) { @@ -81,15 +87,23 @@ await Task.WhenAll(serversToDispose.Select(async server => { // Start the server we just created: await server.StartAsync(cancellationToken); - server.SetEnvironmentVariables(environmentBuilder); } - else + + server.SetEnvironmentVariables(environmentBuilder); + + return server; + } + + bool IStaticAssetChangeApplierProvider.TryGetApplier(ProjectGraphNode projectNode, [NotNullWhen(true)] out IStaticAssetChangeApplier? applier) + { + if (TryGetRefreshServer(projectNode, out var server)) { - // Notify the browser of a project rebuild (delta applier notifies of updates): - await server.SendWaitMessageAsync(cancellationToken); + applier = server; + return true; } - return server; + applier = null; + return false; } public bool TryGetRefreshServer(ProjectGraphNode projectNode, [NotNullWhen(true)] out BrowserRefreshServer? server) @@ -117,6 +131,10 @@ public bool TryGetRefreshServer(ProjectGraphNode projectNode, [NotNullWhen(true) bool matchFound = false; + // Workaround for Aspire dashboard launching: scan for "Login to the dashboard at " prefix in the output and use the URL. + // TODO: Share launch profile processing logic as implemented in VS with dotnet-run and implement browser launching there. + var isAspireHost = projectNode.GetCapabilities().Contains(AspireServiceFactory.AppHostProjectCapability); + return handler; void handler(OutputLine line) @@ -129,7 +147,7 @@ void handler(OutputLine line) return; } - var match = s_nowListeningRegex.Match(line.Content); + var match = (isAspireHost ? s_aspireDashboardUrlRegex : s_nowListeningRegex).Match(line.Content); if (!match.Success) { return; @@ -137,11 +155,12 @@ void handler(OutputLine line) matchFound = true; - var projectAddedToAttemptedSet = ImmutableInterlocked.Update(ref _browserLaunchAttempted, static (set, projectNode) => set.Add(projectNode), projectNode); - if (projectAddedToAttemptedSet) + if (projectOptions.IsRootProject && + ImmutableInterlocked.Update(ref _browserLaunchAttempted, static (set, projectNode) => set.Add(projectNode), projectNode)) { - // first iteration: - LaunchBrowser(launchProfile, match.Groups["url"].Value, server); + // first build iteration of a root project: + var launchUrl = GetLaunchUrl(launchProfile.LaunchUrl, match.Groups["url"].Value); + LaunchBrowser(launchUrl, server); } else if (server != null) { @@ -153,10 +172,15 @@ void handler(OutputLine line) } } - private void LaunchBrowser(LaunchSettingsProfile launchProfile, string launchUrl, BrowserRefreshServer? server) + public static string GetLaunchUrl(string? profileLaunchUrl, string outputLaunchUrl) + => string.IsNullOrWhiteSpace(profileLaunchUrl) ? outputLaunchUrl : + Uri.TryCreate(profileLaunchUrl, UriKind.Absolute, out _) ? profileLaunchUrl : + Uri.TryCreate(outputLaunchUrl, UriKind.Absolute, out var launchUri) ? new Uri(launchUri, profileLaunchUrl).ToString() : + outputLaunchUrl; + + private void LaunchBrowser(string launchUrl, BrowserRefreshServer? server) { - var launchPath = launchProfile.LaunchUrl; - var fileName = Uri.TryCreate(launchPath, UriKind.Absolute, out _) ? launchPath : launchUrl + "/" + launchPath; + var fileName = launchUrl; var args = string.Empty; if (EnvironmentVariables.BrowserPath is { } browserPath) diff --git a/src/BuiltInTools/dotnet-watch/Browser/BrowserRefreshServer.cs b/src/BuiltInTools/dotnet-watch/Browser/BrowserRefreshServer.cs index 0f7c737e5687..ec9e12e07a87 100644 --- a/src/BuiltInTools/dotnet-watch/Browser/BrowserRefreshServer.cs +++ b/src/BuiltInTools/dotnet-watch/Browser/BrowserRefreshServer.cs @@ -22,7 +22,7 @@ namespace Microsoft.DotNet.Watch /// /// Communicates with aspnetcore-browser-refresh.js loaded in the browser. /// - internal sealed class BrowserRefreshServer : IAsyncDisposable + internal sealed class BrowserRefreshServer : IAsyncDisposable, IStaticAssetChangeApplier { private static readonly ReadOnlyMemory s_reloadMessage = Encoding.UTF8.GetBytes("Reload"); private static readonly ReadOnlyMemory s_waitMessage = Encoding.UTF8.GetBytes("Wait"); @@ -81,8 +81,8 @@ public void SetEnvironmentVariables(EnvironmentVariablesBuilder environmentBuild environmentBuilder.SetVariable(EnvironmentVariables.Names.AspNetCoreAutoReloadWSEndPoint, _serverUrls); environmentBuilder.SetVariable(EnvironmentVariables.Names.AspNetCoreAutoReloadWSKey, GetServerKey()); - environmentBuilder.DotNetStartupHookDirective.Add(Path.Combine(AppContext.BaseDirectory, "middleware", "Microsoft.AspNetCore.Watch.BrowserRefresh.dll")); - environmentBuilder.AspNetCoreHostingStartupAssembliesVariable.Add("Microsoft.AspNetCore.Watch.BrowserRefresh"); + environmentBuilder.DotNetStartupHooks.Add(Path.Combine(AppContext.BaseDirectory, "middleware", "Microsoft.AspNetCore.Watch.BrowserRefresh.dll")); + environmentBuilder.AspNetCoreHostingStartupAssemblies.Add("Microsoft.AspNetCore.Watch.BrowserRefresh"); if (_reporter.IsVerbose) { @@ -288,7 +288,7 @@ public ValueTask SendReloadMessageAsync(CancellationToken cancellationToken) public ValueTask SendWaitMessageAsync(CancellationToken cancellationToken) => SendAsync(s_waitMessage, cancellationToken); - public ValueTask SendAsync(ReadOnlyMemory messageBytes, CancellationToken cancellationToken) + private ValueTask SendAsync(ReadOnlyMemory messageBytes, CancellationToken cancellationToken) => SendAndReceiveAsync(request: _ => messageBytes, response: null, cancellationToken); public async ValueTask SendAndReceiveAsync( @@ -354,6 +354,17 @@ public ValueTask ReportCompilationErrorsInBrowserAsync(ImmutableArray co } } + public async ValueTask UpdateStaticAssetsAsync(IEnumerable relativeUrls, CancellationToken cancellationToken) + { + // Serialize all requests sent to a single server: + foreach (var relativeUrl in relativeUrls) + { + _reporter.Verbose($"Sending static asset update request to browser: '{relativeUrl}'."); + var message = JsonSerializer.SerializeToUtf8Bytes(new UpdateStaticFileMessage { Path = relativeUrl }, s_jsonSerializerOptions); + await SendAsync(message, cancellationToken); + } + } + private readonly struct AspNetCoreHotReloadApplied { public string Type => "AspNetCoreHotReloadApplied"; @@ -365,5 +376,11 @@ private readonly struct HotReloadDiagnostics public IEnumerable Diagnostics { get; init; } } + + private readonly struct UpdateStaticFileMessage + { + public string Type => "UpdateStaticFile"; + public string Path { get; init; } + } } } diff --git a/src/BuiltInTools/dotnet-watch/DotNetWatcher.cs b/src/BuiltInTools/dotnet-watch/DotNetWatcher.cs index 321ad2924813..9fcedd45853c 100644 --- a/src/BuiltInTools/dotnet-watch/DotNetWatcher.cs +++ b/src/BuiltInTools/dotnet-watch/DotNetWatcher.cs @@ -62,10 +62,10 @@ public override async Task WatchAsync(CancellationToken shutdownCancellationToke }; var browserRefreshServer = (projectRootNode != null) - ? await browserConnector.LaunchOrRefreshBrowserAsync(projectRootNode, processSpec, environmentBuilder, Context.RootProjectOptions, shutdownCancellationToken) + ? await browserConnector.GetOrCreateBrowserRefreshServerAsync(projectRootNode, processSpec, environmentBuilder, Context.RootProjectOptions, shutdownCancellationToken) : null; - environmentBuilder.ConfigureProcess(processSpec); + environmentBuilder.SetProcessEnvironmentVariables(processSpec); // Reset for next run buildEvaluator.RequiresRevaluation = false; diff --git a/src/BuiltInTools/dotnet-watch/EnvironmentOptions.cs b/src/BuiltInTools/dotnet-watch/EnvironmentOptions.cs index 43d17a2312cb..199c4d864fc2 100644 --- a/src/BuiltInTools/dotnet-watch/EnvironmentOptions.cs +++ b/src/BuiltInTools/dotnet-watch/EnvironmentOptions.cs @@ -27,6 +27,7 @@ internal enum TestFlags internal sealed record EnvironmentOptions( string WorkingDirectory, string MuxerPath, + TimeSpan ProcessCleanupTimeout, bool IsPollingEnabled = false, bool SuppressHandlingStaticContentFiles = false, bool SuppressMSBuildIncrementalism = false, @@ -40,6 +41,7 @@ internal sealed record EnvironmentOptions( ( WorkingDirectory: Directory.GetCurrentDirectory(), MuxerPath: GetMuxerPathFromEnvironment(), + ProcessCleanupTimeout: EnvironmentVariables.ProcessCleanupTimeout, IsPollingEnabled: EnvironmentVariables.IsPollingEnabled, SuppressHandlingStaticContentFiles: EnvironmentVariables.SuppressHandlingStaticContentFiles, SuppressMSBuildIncrementalism: EnvironmentVariables.SuppressMSBuildIncrementalism, diff --git a/src/BuiltInTools/dotnet-watch/EnvironmentVariables.cs b/src/BuiltInTools/dotnet-watch/EnvironmentVariables.cs index c31413b1d3f2..6893ab561060 100644 --- a/src/BuiltInTools/dotnet-watch/EnvironmentVariables.cs +++ b/src/BuiltInTools/dotnet-watch/EnvironmentVariables.cs @@ -3,9 +3,9 @@ namespace Microsoft.DotNet.Watch; -internal static partial class EnvironmentVariables +internal static class EnvironmentVariables { - public static partial class Names + public static class Names { public const string DotnetWatch = "DOTNET_WATCH"; public const string DotnetWatchIteration = "DOTNET_WATCH_ITERATION"; @@ -16,12 +16,19 @@ public static partial class Names public const string AspNetCoreHostingStartupAssemblies = "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES"; public const string AspNetCoreAutoReloadWSEndPoint = "ASPNETCORE_AUTO_RELOAD_WS_ENDPOINT"; public const string AspNetCoreAutoReloadWSKey = "ASPNETCORE_AUTO_RELOAD_WS_KEY"; + + public const string DotNetWatchHotReloadNamedPipeName = HotReload.AgentEnvironmentVariables.DotNetWatchHotReloadNamedPipeName; + public const string DotNetWatchHotReloadTargetProcessPath = HotReload.AgentEnvironmentVariables.DotNetWatchHotReloadTargetProcessPath; + public const string DotNetStartupHooks = HotReload.AgentEnvironmentVariables.DotNetStartupHooks; + public const string DotNetModifiableAssemblies = HotReload.AgentEnvironmentVariables.DotNetModifiableAssemblies; + public const string HotReloadDeltaClientLogMessages = HotReload.AgentEnvironmentVariables.HotReloadDeltaClientLogMessages; } public static bool VerboseCliOutput => ReadBool("DOTNET_CLI_CONTEXT_VERBOSE"); public static bool IsPollingEnabled => ReadBool("DOTNET_USE_POLLING_FILE_WATCHER"); public static bool SuppressEmojis => ReadBool("DOTNET_WATCH_SUPPRESS_EMOJIS"); public static bool RestartOnRudeEdit => ReadBool("DOTNET_WATCH_RESTART_ON_RUDE_EDIT"); + public static TimeSpan ProcessCleanupTimeout => ReadTimeSpan("DOTNET_WATCH_PROCESS_CLEANUP_TIMEOUT_MS"); public static string SdkRootDirectory => #if DEBUG @@ -43,4 +50,7 @@ public static partial class Names private static bool ReadBool(string variableName) => Environment.GetEnvironmentVariable(variableName) is var value && (value == "1" || bool.TryParse(value, out var boolValue) && boolValue); + + private static TimeSpan ReadTimeSpan(string variableName) + => Environment.GetEnvironmentVariable(variableName) is var value && long.TryParse(value, out var intValue) && intValue >= 0 ? TimeSpan.FromMilliseconds(intValue) : TimeSpan.FromSeconds(5); } diff --git a/src/BuiltInTools/dotnet-watch/EnvironmentVariablesBuilder.cs b/src/BuiltInTools/dotnet-watch/EnvironmentVariablesBuilder.cs index aec5634a4acf..640389af9175 100644 --- a/src/BuiltInTools/dotnet-watch/EnvironmentVariablesBuilder.cs +++ b/src/BuiltInTools/dotnet-watch/EnvironmentVariablesBuilder.cs @@ -10,89 +10,64 @@ internal sealed class EnvironmentVariablesBuilder private static readonly char s_startupHooksSeparator = Path.PathSeparator; private const char AssembliesSeparator = ';'; - public List DotNetStartupHookDirective { get; } = []; - public List AspNetCoreHostingStartupAssembliesVariable { get; } = []; + public List DotNetStartupHooks { get; } = []; + public List AspNetCoreHostingStartupAssemblies { get; } = []; /// /// Environment variables set on the dotnet run process. /// private readonly Dictionary _variables = []; - /// - /// Environment variables passed as directives on command line (dotnet [env:name=value] run). - /// Currently, the effect is the same as setting due to - /// https://github.com/dotnet/sdk/issues/40484 - /// - private readonly Dictionary _directives = []; - public static EnvironmentVariablesBuilder FromCurrentEnvironment() { var builder = new EnvironmentVariablesBuilder(); - if (Environment.GetEnvironmentVariable(EnvironmentVariables.Names.DotnetStartupHooks) is { } dotnetStartupHooks) + if (Environment.GetEnvironmentVariable(EnvironmentVariables.Names.DotNetStartupHooks) is { } dotnetStartupHooks) { - builder.DotNetStartupHookDirective.AddRange(dotnetStartupHooks.Split(s_startupHooksSeparator)); + builder.DotNetStartupHooks.AddRange(dotnetStartupHooks.Split(s_startupHooksSeparator)); } if (Environment.GetEnvironmentVariable(EnvironmentVariables.Names.AspNetCoreHostingStartupAssemblies) is { } assemblies) { - builder.AspNetCoreHostingStartupAssembliesVariable.AddRange(assemblies.Split(AssembliesSeparator)); + builder.AspNetCoreHostingStartupAssemblies.AddRange(assemblies.Split(AssembliesSeparator)); } return builder; } - public void SetDirective(string name, string value) - { - // should use DotNetStartupHookDirective - Debug.Assert(!name.Equals(EnvironmentVariables.Names.DotnetStartupHooks, StringComparison.OrdinalIgnoreCase)); - - _directives[name] = value; - } - public void SetVariable(string name, string value) { - // should use AspNetCoreHostingStartupAssembliesVariable + // should use AspNetCoreHostingStartupAssembliesVariable/DotNetStartupHookDirective Debug.Assert(!name.Equals(EnvironmentVariables.Names.AspNetCoreHostingStartupAssemblies, StringComparison.OrdinalIgnoreCase)); + Debug.Assert(!name.Equals(EnvironmentVariables.Names.DotNetStartupHooks, StringComparison.OrdinalIgnoreCase)); _variables[name] = value; } - public void ConfigureProcess(ProcessSpec processSpec) + public void SetProcessEnvironmentVariables(ProcessSpec processSpec) { - processSpec.Arguments = [.. GetCommandLineDirectives(), .. processSpec.Arguments ?? []]; - AddToEnvironment(processSpec.EnvironmentVariables); + foreach (var (name, value) in GetEnvironment()) + { + processSpec.EnvironmentVariables.Add(name, value); + } } - // for testing - internal void AddToEnvironment(Dictionary variables) + public IEnumerable<(string name, string value)> GetEnvironment() { foreach (var (name, value) in _variables) { - variables.Add(name, value); + yield return (name, value); } - if (AspNetCoreHostingStartupAssembliesVariable is not []) + if (DotNetStartupHooks is not []) { - variables.Add(EnvironmentVariables.Names.AspNetCoreHostingStartupAssemblies, string.Join(AssembliesSeparator, AspNetCoreHostingStartupAssembliesVariable)); + yield return (EnvironmentVariables.Names.DotNetStartupHooks, string.Join(s_startupHooksSeparator, DotNetStartupHooks)); } - } - // for testing - internal IEnumerable GetCommandLineDirectives() - { - foreach (var (name, value) in _directives) + if (AspNetCoreHostingStartupAssemblies is not []) { - yield return MakeDirective(name, value); + yield return (EnvironmentVariables.Names.AspNetCoreHostingStartupAssemblies, string.Join(AssembliesSeparator, AspNetCoreHostingStartupAssemblies)); } - - if (DotNetStartupHookDirective is not []) - { - yield return MakeDirective(EnvironmentVariables.Names.DotnetStartupHooks, string.Join(s_startupHooksSeparator, DotNetStartupHookDirective)); - } - - static string MakeDirective(string name, string value) - => $"[env:{name}={value}]"; } } } diff --git a/src/BuiltInTools/dotnet-watch/EnvironmentVariables_StartupHook.cs b/src/BuiltInTools/dotnet-watch/EnvironmentVariables_StartupHook.cs deleted file mode 100644 index 6a9191c1dab7..000000000000 --- a/src/BuiltInTools/dotnet-watch/EnvironmentVariables_StartupHook.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace Microsoft.DotNet.Watch; - -internal static partial class EnvironmentVariables -{ - public static partial class Names - { - /// - /// Intentionally different from the variable name used by the debugger. - /// This is to avoid the debugger colliding with dotnet-watch pipe connection when debugging dotnet-watch (or tests). - /// - public const string DotnetWatchHotReloadNamedPipeName = "DOTNET_WATCH_HOTRELOAD_NAMEDPIPE_NAME"; - - /// - /// The full path to the process being launched by dotnet run. - /// Workaround for https://github.com/dotnet/sdk/issues/40484 - /// - public const string DotnetWatchHotReloadTargetProcessPath = "DOTNET_WATCH_HOTRELOAD_TARGET_PROCESS_PATH"; - - /// - /// Enables logging from the client delta applier agent. - /// - public const string HotReloadDeltaClientLogMessages = "HOTRELOAD_DELTA_CLIENT_LOG_MESSAGES"; - - public const string DotnetStartupHooks = "DOTNET_STARTUP_HOOKS"; - public const string DotnetModifiableAssemblies = "DOTNET_MODIFIABLE_ASSEMBLIES"; - } -} diff --git a/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyDeltaApplier.cs b/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyDeltaApplier.cs index 35d0828ad56a..617d7d733856 100644 --- a/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyDeltaApplier.cs +++ b/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyDeltaApplier.cs @@ -67,7 +67,7 @@ public override Task> GetApplyUpdateCapabilitiesAsync(Can return Task.FromResult(capabilities); } - public override async Task Apply(ImmutableArray updates, CancellationToken cancellationToken) + public override async Task ApplyManagedCodeUpdates(ImmutableArray updates, CancellationToken cancellationToken) { var applicableUpdates = await FilterApplicableUpdatesAsync(updates, cancellationToken); if (applicableUpdates.Count == 0) @@ -135,6 +135,13 @@ await browserRefreshServer.SendAndReceiveAsync( return (!anySuccess && anyFailure) ? ApplyStatus.Failed : (applicableUpdates.Count < updates.Length) ? ApplyStatus.SomeChangesApplied : ApplyStatus.AllChangesApplied; } + public override Task ApplyStaticAssetUpdates(ImmutableArray updates, CancellationToken cancellationToken) + // static asset updates are handled by browser refresh server: + => Task.FromResult(ApplyStatus.NoChangesApplied); + + public override Task InitialUpdatesApplied(CancellationToken cancellationToken) + => Task.CompletedTask; + private readonly struct JsonApplyHotReloadDeltasRequest { public string Type => "BlazorHotReloadDeltav3"; diff --git a/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyHostedDeltaApplier.cs b/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyHostedDeltaApplier.cs index f2eb00de24bc..2499e85e13c1 100644 --- a/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyHostedDeltaApplier.cs +++ b/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyHostedDeltaApplier.cs @@ -41,7 +41,7 @@ public override async Task> GetApplyUpdateCapabilitiesAsy return result[0].Union(result[1], StringComparer.OrdinalIgnoreCase).ToImmutableArray(); } - public override async Task Apply(ImmutableArray updates, CancellationToken cancellationToken) + public override async Task ApplyManagedCodeUpdates(ImmutableArray updates, CancellationToken cancellationToken) { // Apply to both processes. // The module the change is for does not need to be loaded in either of the processes, yet we still consider it successful if the application does not fail. @@ -50,8 +50,8 @@ public override async Task Apply(ImmutableArray ApplyStaticAssetUpdates(ImmutableArray updates, CancellationToken cancellationToken) + // static asset updates are handled by browser refresh server: + => Task.FromResult(ApplyStatus.NoChangesApplied); + + public override Task InitialUpdatesApplied(CancellationToken cancellationToken) + => _hostApplier.InitialUpdatesApplied(cancellationToken); } } diff --git a/src/BuiltInTools/dotnet-watch/HotReload/CompilationHandler.cs b/src/BuiltInTools/dotnet-watch/HotReload/CompilationHandler.cs index 838c3f97ab70..15c4ea831d9b 100644 --- a/src/BuiltInTools/dotnet-watch/HotReload/CompilationHandler.cs +++ b/src/BuiltInTools/dotnet-watch/HotReload/CompilationHandler.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. - using System.Collections.Immutable; using System.Diagnostics; using Microsoft.Build.Graph; @@ -15,6 +14,7 @@ namespace Microsoft.DotNet.Watch internal sealed class CompilationHandler : IDisposable { public readonly IncrementalMSBuildWorkspace Workspace; + public readonly EnvironmentOptions EnvironmentOptions; private readonly IReporter _reporter; private readonly WatchHotReloadService _hotReloadService; @@ -37,19 +37,17 @@ internal sealed class CompilationHandler : IDisposable /// private ImmutableList _previousUpdates = []; - /// - /// Set of capabilities aggregated across the current set of . - /// Default if not calculated yet. - /// - private ImmutableArray _currentAggregateCapabilities; + private readonly CancellationToken _shutdownCancellationToken; private bool _isDisposed; - public CompilationHandler(IReporter reporter) + public CompilationHandler(IReporter reporter, EnvironmentOptions environmentOptions, CancellationToken shutdownCancellationToken) { _reporter = reporter; + EnvironmentOptions = environmentOptions; Workspace = new IncrementalMSBuildWorkspace(reporter); - _hotReloadService = new WatchHotReloadService(Workspace.CurrentSolution.Services, GetAggregateCapabilitiesAsync); + _hotReloadService = new WatchHotReloadService(Workspace.CurrentSolution.Services, () => ValueTask.FromResult(GetAggregateCapabilities())); + _shutdownCancellationToken = shutdownCancellationToken; } public void Dispose() @@ -150,10 +148,14 @@ private static DeltaApplier CreateDeltaApplier(HotReloadProfile profile, Project return null; } - var capabilityProvider = deltaApplier.GetApplyUpdateCapabilitiesAsync(processCommunicationCancellationSource.Token); + // Wait for agent to create the name pipe and send capabilities over. + // the agent blocks the app execution until initial updates are applied (if any). + var capabilities = await deltaApplier.GetApplyUpdateCapabilitiesAsync(processCommunicationCancellationSource.Token); + var runningProject = new RunningProject( projectNode, projectOptions, + EnvironmentOptions, deltaApplier, processReporter, browserRefreshServer, @@ -163,24 +165,22 @@ private static DeltaApplier CreateDeltaApplier(HotReloadProfile profile, Project processTerminationSource: processTerminationSource, restartOperation: restartOperation, disposables: [processCommunicationCancellationSource], - capabilityProvider); + capabilities); // ownership transferred to running project: disposables.Items.Clear(); disposables.Items.Add(runningProject); - ImmutableArray observedCapabilities = default; - var appliedUpdateCount = 0; while (true) { // Observe updates that need to be applied to the new process // and apply them before adding it to running processes. - // Do bot block on udpates being made to other processes to avoid delaying the new process being up-to-date. + // Do not block on udpates being made to other processes to avoid delaying the new process being up-to-date. var updatesToApply = _previousUpdates.Skip(appliedUpdateCount).ToImmutableArray(); if (updatesToApply.Any()) { - _ = await deltaApplier.Apply(updatesToApply, processCommunicationCancellationSource.Token); + _ = await deltaApplier.ApplyManagedCodeUpdates(updatesToApply, processCommunicationCancellationSource.Token); } appliedUpdateCount += updatesToApply.Length; @@ -205,26 +205,18 @@ private static DeltaApplier CreateDeltaApplier(HotReloadProfile profile, Project _runningProjects = _runningProjects.SetItem(projectPath, projectInstances.Add(runningProject)); - // reset capabilities: - observedCapabilities = _currentAggregateCapabilities; - _currentAggregateCapabilities = default; - // ownership transferred to _runningProjects disposables.Items.Clear(); break; } } + // Notifies the agent that it can unblock the execution of the process: + await deltaApplier.InitialUpdatesApplied(cancellationToken); + // If non-empty solution is loaded into the workspace (a Hot Reload session is active): if (Workspace.CurrentSolution is { ProjectIds: not [] } currentSolution) { - // If capabilities have been observed by an edit session, restart the session. Next time EnC service needs - // capabilities it calls GetAggregateCapabilitiesAsync which uses the set of projects assigned above to calculate them. - if (!observedCapabilities.IsDefault) - { - _hotReloadService.CapabilitiesChanged(); - } - // Preparing the compilation is a perf optimization. We can skip it if the session hasn't been started yet. PrepareCompilations(currentSolution, projectPath, cancellationToken); } @@ -232,33 +224,13 @@ private static DeltaApplier CreateDeltaApplier(HotReloadProfile profile, Project return runningProject; } - private async ValueTask> GetAggregateCapabilitiesAsync() + private ImmutableArray GetAggregateCapabilities() { - var capabilities = _currentAggregateCapabilities; - if (!capabilities.IsDefault) - { - return capabilities; - } - - while (true) - { - var runningProjects = _runningProjects; - var capabilitiesByProvider = await Task.WhenAll(runningProjects.SelectMany(p => p.Value).Select(p => p.CapabilityProvider)); - capabilities = capabilitiesByProvider.SelectMany(c => c).Distinct(StringComparer.Ordinal).ToImmutableArray(); - - lock (_runningProjectsAndUpdatesGuard) - { - if (runningProjects != _runningProjects) - { - // Another process has been launched while we were retrieving capabilities, query the providers again. - // The providers cache the result so we won't be calling into the respective processes again. - continue; - } - - _currentAggregateCapabilities = capabilities; - break; - } - } + var capabilities = _runningProjects + .SelectMany(p => p.Value) + .SelectMany(p => p.Capabilities) + .Distinct(StringComparer.Ordinal) + .ToImmutableArray(); _reporter.Verbose($"Hot reload capabilities: {string.Join(" ", capabilities)}.", emoji: "🔥"); return capabilities; @@ -277,7 +249,7 @@ private static void PrepareCompilations(Solution solution, string projectPath, C } } - public async ValueTask<(ImmutableDictionary projectsToRebuild, ImmutableArray terminatedProjects)> HandleFileChangesAsync( + public async ValueTask<(ImmutableDictionary projectsToRebuild, ImmutableArray terminatedProjects)> HandleManagedCodeChangesAsync( Func, CancellationToken, Task> restartPrompt, CancellationToken cancellationToken) { @@ -337,7 +309,7 @@ await ForEachProjectAsync(projectsToUpdate, async (runningProject, cancellationT try { using var processCommunicationCancellationSource = CancellationTokenSource.CreateLinkedTokenSource(runningProject.ProcessExitedSource.Token, cancellationToken); - var applySucceded = await runningProject.DeltaApplier.Apply(updates.ProjectUpdates, processCommunicationCancellationSource.Token) != ApplyStatus.Failed; + var applySucceded = await runningProject.DeltaApplier.ApplyManagedCodeUpdates(updates.ProjectUpdates, processCommunicationCancellationSource.Token) != ApplyStatus.Failed; if (applySucceded) { runningProject.Reporter.Report(MessageDescriptor.HotReloadSucceeded); @@ -364,7 +336,7 @@ private async ValueTask DisplayResultsAsync(WatchHotReloadService.Updates update switch (updates.Status) { case ModuleUpdateStatus.None: - _reporter.Report(MessageDescriptor.NoHotReloadChangesToApply); + _reporter.Report(MessageDescriptor.NoCSharpChangesToApply); break; case ModuleUpdateStatus.Ready: @@ -465,6 +437,102 @@ await ForEachProjectAsync( cancellationToken); } + public async ValueTask HandleStaticAssetChangesAsync(IReadOnlyList files, ProjectNodeMap projectMap, CancellationToken cancellationToken) + { + var allFilesHandled = true; + + var updates = new Dictionary>(); + + foreach (var changedFile in files) + { + var file = changedFile.Item; + + if (file.StaticWebAssetPath is null) + { + allFilesHandled = false; + continue; + } + + foreach (var containingProjectPath in file.ContainingProjectPaths) + { + if (!projectMap.Map.TryGetValue(containingProjectPath, out var containingProjectNodes)) + { + // Shouldn't happen. + _reporter.Warn($"Project '{containingProjectPath}' not found in the project graph."); + continue; + } + + foreach (var containingProjectNode in containingProjectNodes) + { + foreach (var referencingProjectNode in new[] { containingProjectNode }.GetTransitivelyReferencingProjects()) + { + if (TryGetRunningProject(referencingProjectNode.ProjectInstance.FullPath, out var runningProjects)) + { + foreach (var runningProject in runningProjects) + { + if (!updates.TryGetValue(runningProject, out var updatesPerRunningProject)) + { + updates.Add(runningProject, updatesPerRunningProject = []); + } + + updatesPerRunningProject.Add((file.FilePath, file.StaticWebAssetPath, containingProjectNode)); + } + } + } + } + } + } + + if (updates.Count == 0) + { + return allFilesHandled; + } + + var tasks = updates.Select(async entry => + { + var (runningProject, assets) = entry; + + if (runningProject.BrowserRefreshServer != null) + { + await runningProject.BrowserRefreshServer.UpdateStaticAssetsAsync(assets.Select(a => a.relativeUrl), cancellationToken); + } + else + { + var updates = new List(); + + foreach (var (filePath, relativeUrl, containingProject) in assets) + { + byte[] content; + try + { + content = await File.ReadAllBytesAsync(filePath, cancellationToken); + } + catch (Exception e) + { + _reporter.Error(e.Message); + continue; + } + + updates.Add(new StaticAssetUpdate( + relativePath: relativeUrl, + assemblyName: containingProject.GetAssemblyName(), + content: content, + isApplicationProject: containingProject == runningProject.ProjectNode)); + + _reporter.Verbose($"Sending static file update request for asset '{relativeUrl}'."); + } + + await runningProject.DeltaApplier.ApplyStaticAssetUpdates([.. updates], cancellationToken); + } + }); + + await Task.WhenAll(tasks).WaitAsync(cancellationToken); + + _reporter.Output("Hot reload of static files succeeded.", emoji: "🔥"); + + return allFilesHandled; + } + /// /// Terminates all processes launched for projects with , /// or all running non-root project processes if is null. @@ -536,22 +604,21 @@ private void UpdateRunningProjects(Func> TerminateRunningProjects(IEnumerable projects, CancellationToken cancellationToken) + public bool TryGetRunningProject(string projectPath, out ImmutableArray projects) { - // cancel first, this will cause the process tasks to complete: - foreach (var project in projects) + lock (_runningProjectsAndUpdatesGuard) { - project.ProcessTerminationSource.Cancel(); + return _runningProjects.TryGetValue(projectPath, out projects); } + } + private async ValueTask> TerminateRunningProjects(IEnumerable projects, CancellationToken cancellationToken) + { // wait for all tasks to complete: - return await Task.WhenAll(projects.Select(p => p.RunningProcess)).WaitAsync(cancellationToken); + return await Task.WhenAll(projects.Select(p => p.TerminateAsync(_shutdownCancellationToken).AsTask())).WaitAsync(cancellationToken); } private static Task ForEachProjectAsync(ImmutableDictionary> projects, Func action, CancellationToken cancellationToken) diff --git a/src/BuiltInTools/dotnet-watch/HotReload/DefaultDeltaApplier.cs b/src/BuiltInTools/dotnet-watch/HotReload/DefaultDeltaApplier.cs index a3228802a53e..5d7f507984cc 100644 --- a/src/BuiltInTools/dotnet-watch/HotReload/DefaultDeltaApplier.cs +++ b/src/BuiltInTools/dotnet-watch/HotReload/DefaultDeltaApplier.cs @@ -15,7 +15,7 @@ internal sealed class DefaultDeltaApplier(IReporter reporter) : SingleProcessDel { private Task>? _capabilitiesTask; private NamedPipeServerStream? _pipe; - private bool _changeApplicationErrorFailed; + private bool _managedCodeUpdateFailedOrCancelled; public override void CreateConnection(string namedPipeName, CancellationToken cancellationToken) { @@ -36,7 +36,7 @@ async Task> ConnectAsync() // When the client connects, the first payload it sends is the initialization payload which includes the apply capabilities. - var capabilities = (await ClientInitializationPayload.ReadAsync(_pipe, cancellationToken)).Capabilities; + var capabilities = (await ClientInitializationResponse.ReadAsync(_pipe, cancellationToken)).Capabilities; Reporter.Verbose($"Capabilities: '{capabilities}'"); return [.. capabilities.Split(' ')]; } @@ -66,7 +66,10 @@ public override Task> GetApplyUpdateCapabilitiesAsync(Can // Should only be called after CreateConnection => _capabilitiesTask ?? throw new InvalidOperationException(); - public override async Task Apply(ImmutableArray updates, CancellationToken cancellationToken) + private ResponseLoggingLevel ResponseLoggingLevel + => Reporter.IsVerbose ? ResponseLoggingLevel.Verbose : ResponseLoggingLevel.WarningsAndErrors; + + public override async Task ApplyManagedCodeUpdates(ImmutableArray updates, CancellationToken cancellationToken) { // Should only be called after CreateConnection Debug.Assert(_capabilitiesTask != null); @@ -74,7 +77,7 @@ public override async Task Apply(ImmutableArray Apply(ImmutableArray new UpdateDelta( + var request = new ManagedCodeUpdateRequest( + deltas: [.. applicableUpdates.Select(update => new UpdateDelta( update.ModuleId, - metadataDelta: update.MetadataDelta.ToArray(), - ilDelta: update.ILDelta.ToArray(), - pdbDelta: update.PdbDelta.ToArray(), - update.UpdatedTypes.ToArray())).ToArray(), - responseLoggingLevel: Reporter.IsVerbose ? ResponseLoggingLevel.Verbose : ResponseLoggingLevel.WarningsAndErrors); + metadataDelta: [.. update.MetadataDelta], + ilDelta: [.. update.ILDelta], + pdbDelta: [.. update.PdbDelta], + updatedTypes: [.. update.UpdatedTypes]))], + responseLoggingLevel: ResponseLoggingLevel); var success = false; var canceled = false; try { - await payload.WriteAsync(_pipe, cancellationToken); - await _pipe.FlushAsync(cancellationToken); - success = await ReceiveApplyUpdateResult(cancellationToken); + success = await SendAndReceiveUpdate(request, cancellationToken); } catch (OperationCanceledException) when (!(canceled = true)) { + // unreachable } catch (Exception e) when (e is not OperationCanceledException) { + success = false; Reporter.Error($"Change failed to apply (error: '{e.Message}'). Further changes won't be applied to this process."); Reporter.Verbose($"Exception stack trace: {e.StackTrace}", "❌"); } @@ -121,7 +124,7 @@ public override async Task Apply(ImmutableArray Apply(ImmutableArray ReceiveApplyUpdateResult(CancellationToken cancellationToken) + public async override Task ApplyStaticAssetUpdates(ImmutableArray updates, CancellationToken cancellationToken) { - Debug.Assert(_pipe != null); + var appliedUpdateCount = 0; - var status = ArrayPool.Shared.Rent(1); - try + foreach (var update in updates) { - var statusBytesRead = await _pipe.ReadAsync(status, offset: 0, count: 1, cancellationToken); - if (statusBytesRead != 1 || status[0] != UpdatePayload.ApplySuccessValue) + var request = new StaticAssetUpdateRequest( + update.AssemblyName, + update.RelativePath, + update.Content, + update.IsApplicationProject, + ResponseLoggingLevel); + + var success = false; + var canceled = false; + try + { + success = await SendAndReceiveUpdate(request, cancellationToken); + } + catch (OperationCanceledException) when (!(canceled = true)) { - var message = (statusBytesRead == 0) ? "received no data" : $"received status 0x{status[0]:x2}"; - Reporter.Error($"Change failed to apply ({message}). Further changes won't be applied to this process."); - return false; + // unreachable + } + catch (Exception e) when (e is not OperationCanceledException) + { + success = false; + Reporter.Error($"Change failed to apply (error: '{e.Message}')."); + Reporter.Verbose($"Exception stack trace: {e.StackTrace}", "❌"); + } + finally + { + if (canceled) + { + Reporter.Verbose("Change application cancelled.", "🔥"); + } } - await foreach (var (message, severity) in UpdatePayload.ReadLogAsync(_pipe, cancellationToken)) + if (success) { - ReportLogEntry(Reporter, message, severity); + appliedUpdateCount++; } + } + + Reporter.Report(MessageDescriptor.UpdatesApplied, appliedUpdateCount, updates.Length); + + return + (appliedUpdateCount == 0) ? ApplyStatus.Failed : + (appliedUpdateCount < updates.Length) ? ApplyStatus.SomeChangesApplied : ApplyStatus.AllChangesApplied; + } - return true; + private async ValueTask SendAndReceiveUpdate(TRequest request, CancellationToken cancellationToken) + where TRequest : IUpdateRequest + { + // Should not be disposed: + Debug.Assert(_pipe != null); + + await _pipe.WriteAsync((byte)request.Type, cancellationToken); + await request.WriteAsync(_pipe, cancellationToken); + await _pipe.FlushAsync(cancellationToken); + + var (success, log) = await UpdateResponse.ReadAsync(_pipe, cancellationToken); + + await foreach (var (message, severity) in log) + { + ReportLogEntry(Reporter, message, severity); } - finally + + return success; + } + + public override async Task InitialUpdatesApplied(CancellationToken cancellationToken) + { + // Should only be called after CreateConnection + Debug.Assert(_capabilitiesTask != null); + + // Should not be disposed: + Debug.Assert(_pipe != null); + + if (_managedCodeUpdateFailedOrCancelled) { - ArrayPool.Shared.Return(status); + return; } + + await _pipe.WriteAsync((byte)RequestType.InitialUpdatesCompleted, cancellationToken); + await _pipe.FlushAsync(cancellationToken); } private void DisposePipe() diff --git a/src/BuiltInTools/dotnet-watch/HotReload/DeltaApplier.cs b/src/BuiltInTools/dotnet-watch/HotReload/DeltaApplier.cs index 78f6a02d01a6..852c9295e949 100644 --- a/src/BuiltInTools/dotnet-watch/HotReload/DeltaApplier.cs +++ b/src/BuiltInTools/dotnet-watch/HotReload/DeltaApplier.cs @@ -24,7 +24,10 @@ internal abstract class DeltaApplier(IReporter reporter) : IDisposable public abstract Task> GetApplyUpdateCapabilitiesAsync(CancellationToken cancellationToken); - public abstract Task Apply(ImmutableArray updates, CancellationToken cancellationToken); + public abstract Task ApplyManagedCodeUpdates(ImmutableArray updates, CancellationToken cancellationToken); + public abstract Task ApplyStaticAssetUpdates(ImmutableArray updates, CancellationToken cancellationToken); + + public abstract Task InitialUpdatesApplied(CancellationToken cancellationToken); public abstract void Dispose(); diff --git a/src/BuiltInTools/dotnet-watch/HotReload/IRuntimeProcessLauncherFactory.cs b/src/BuiltInTools/dotnet-watch/HotReload/IRuntimeProcessLauncherFactory.cs index 431e79830ae3..93d69f69db59 100644 --- a/src/BuiltInTools/dotnet-watch/HotReload/IRuntimeProcessLauncherFactory.cs +++ b/src/BuiltInTools/dotnet-watch/HotReload/IRuntimeProcessLauncherFactory.cs @@ -12,5 +12,5 @@ namespace Microsoft.DotNet.Watch; /// internal interface IRuntimeProcessLauncherFactory { - public IRuntimeProcessLauncher? TryCreate(ProjectGraphNode projectNode, ProjectLauncher projectLauncher, IReadOnlyList buildArguments); + public IRuntimeProcessLauncher? TryCreate(ProjectGraphNode projectNode, ProjectLauncher projectLauncher, ProjectOptions hostProjectOptions); } diff --git a/src/BuiltInTools/dotnet-watch/HotReload/IStaticAssetChangeApplierProvider.cs b/src/BuiltInTools/dotnet-watch/HotReload/IStaticAssetChangeApplierProvider.cs new file mode 100644 index 000000000000..ad2f9491cc70 --- /dev/null +++ b/src/BuiltInTools/dotnet-watch/HotReload/IStaticAssetChangeApplierProvider.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.CodeAnalysis; +using Microsoft.Build.Graph; + +namespace Microsoft.DotNet.Watch; + +internal interface IStaticAssetChangeApplierProvider +{ + bool TryGetApplier(ProjectGraphNode projectNode, [NotNullWhen(true)] out IStaticAssetChangeApplier? applier); +} + +internal interface IStaticAssetChangeApplier +{ +} diff --git a/src/BuiltInTools/dotnet-watch/HotReload/NamedPipeContract.cs b/src/BuiltInTools/dotnet-watch/HotReload/NamedPipeContract.cs deleted file mode 100644 index d95c3e8e5128..000000000000 --- a/src/BuiltInTools/dotnet-watch/HotReload/NamedPipeContract.cs +++ /dev/null @@ -1,431 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Buffers; -using System.Buffers.Binary; -using System.Runtime.CompilerServices; -using Microsoft.DotNet.HotReload; - -namespace Microsoft.DotNet.Watch -{ - internal enum PayloadType - { - ManagedCodeUpdate = 1, - StaticAssetUpdate = 2, - InitialUpdatesCompleted = 3, - } - - internal readonly struct UpdatePayload(IReadOnlyList deltas, ResponseLoggingLevel responseLoggingLevel) - { - public const byte ApplySuccessValue = 0; - - private const byte Version = 4; - - public IReadOnlyList Deltas { get; } = deltas; - public ResponseLoggingLevel ResponseLoggingLevel { get; } = responseLoggingLevel; - - /// - /// Called by the dotnet-watch. - /// - public async ValueTask WriteAsync(Stream stream, CancellationToken cancellationToken) - { - await stream.WriteAsync(Version, cancellationToken); - await stream.WriteAsync(Deltas.Count, cancellationToken); - - foreach (var delta in Deltas) - { - await stream.WriteAsync(delta.ModuleId, cancellationToken); - await stream.WriteByteArrayAsync(delta.MetadataDelta, cancellationToken); - await stream.WriteByteArrayAsync(delta.ILDelta, cancellationToken); - await stream.WriteByteArrayAsync(delta.PdbDelta, cancellationToken); - await stream.WriteAsync(delta.UpdatedTypes, cancellationToken); - } - - await stream.WriteAsync((byte)ResponseLoggingLevel, cancellationToken); - } - - /// - /// Called by the dotnet-watch. - /// - public static async ValueTask WriteLogAsync(Stream stream, IReadOnlyCollection<(string message, AgentMessageSeverity severity)> log, CancellationToken cancellationToken) - { - await stream.WriteAsync(log.Count, cancellationToken); - - foreach (var (message, severity) in log) - { - await stream.WriteAsync(message, cancellationToken); - await stream.WriteAsync((byte)severity, cancellationToken); - } - } - - /// - /// Called by delta applier. - /// - public static async ValueTask ReadAsync(Stream stream, CancellationToken cancellationToken) - { - var version = await stream.ReadByteAsync(cancellationToken); - if (version != Version) - { - throw new NotSupportedException($"Unsupported version {version}."); - } - - var count = await stream.ReadInt32Async(cancellationToken); - - var deltas = new UpdateDelta[count]; - for (var i = 0; i < count; i++) - { - var moduleId = await stream.ReadGuidAsync(cancellationToken); - var metadataDelta = await stream.ReadByteArrayAsync(cancellationToken); - var ilDelta = await stream.ReadByteArrayAsync(cancellationToken); - var pdbDelta = await stream.ReadByteArrayAsync(cancellationToken); - var updatedTypes = await stream.ReadIntArrayAsync(cancellationToken); - - deltas[i] = new UpdateDelta(moduleId, metadataDelta: metadataDelta, ilDelta: ilDelta, pdbDelta: pdbDelta, updatedTypes); - } - - var responseLoggingLevel = (ResponseLoggingLevel)await stream.ReadByteAsync(cancellationToken); - return new UpdatePayload(deltas, responseLoggingLevel: responseLoggingLevel); - } - - /// - /// Called by delta applier. - /// - public static async IAsyncEnumerable<(string message, AgentMessageSeverity severity)> ReadLogAsync(Stream stream, [EnumeratorCancellation] CancellationToken cancellationToken) - { - var entryCount = await stream.ReadInt32Async(cancellationToken); - - for (var i = 0; i < entryCount; i++) - { - var message = await stream.ReadStringAsync(cancellationToken); - var severity = (AgentMessageSeverity)await stream.ReadByteAsync(cancellationToken); - yield return (message, severity); - } - } - } - - internal readonly struct ClientInitializationPayload(string capabilities) - { - private const byte Version = 0; - - public string Capabilities { get; } = capabilities; - - /// - /// Called by delta applier. - /// - public async ValueTask WriteAsync(Stream stream, CancellationToken cancellationToken) - { - await stream.WriteAsync(Version, cancellationToken); - await stream.WriteAsync(Capabilities, cancellationToken); - } - - /// - /// Called by dotnet-watch. - /// - public static async ValueTask ReadAsync(Stream stream, CancellationToken cancellationToken) - { - var version = await stream.ReadByteAsync(cancellationToken); - if (version != Version) - { - throw new NotSupportedException($"Unsupported version {version}."); - } - - var capabilities = await stream.ReadStringAsync(cancellationToken); - return new ClientInitializationPayload(capabilities); - } - } - - internal readonly struct StaticAssetPayload( - string assemblyName, - string relativePath, - byte[] contents, - bool isApplicationProject) - { - private const byte Version = 1; - - public string AssemblyName { get; } = assemblyName; - public bool IsApplicationProject { get; } = isApplicationProject; - public string RelativePath { get; } = relativePath; - public byte[] Contents { get; } = contents; - - public async ValueTask WriteAsync(Stream stream, CancellationToken cancellationToken) - { - await stream.WriteAsync(Version, cancellationToken); - await stream.WriteAsync(AssemblyName, cancellationToken); - await stream.WriteAsync(IsApplicationProject, cancellationToken); - await stream.WriteAsync(RelativePath, cancellationToken); - await stream.WriteByteArrayAsync(Contents, cancellationToken); - } - - public static async ValueTask ReadAsync(Stream stream, CancellationToken cancellationToken) - { - var version = await stream.ReadByteAsync(cancellationToken); - if (version != Version) - { - throw new NotSupportedException($"Unsupported version {version}."); - } - - var assemblyName = await stream.ReadStringAsync(cancellationToken); - var isAppProject = await stream.ReadBooleanAsync(cancellationToken); - var relativePath = await stream.ReadStringAsync(cancellationToken); - var contents = await stream.ReadByteArrayAsync(cancellationToken); - - return new StaticAssetPayload( - assemblyName: assemblyName, - relativePath: relativePath, - contents: contents, - isApplicationProject: isAppProject); - } - } - - /// - /// Implements async read/write helpers that provide functionality of and . - /// See https://github.com/dotnet/runtime/issues/17229 - /// - internal static class StreamExtesions - { - public static ValueTask WriteAsync(this Stream stream, bool value, CancellationToken cancellationToken) - => WriteAsync(stream, (byte)(value ? 1 : 0), cancellationToken); - - public static async ValueTask WriteAsync(this Stream stream, byte value, CancellationToken cancellationToken) - { - var size = sizeof(byte); - var buffer = ArrayPool.Shared.Rent(minimumLength: size); - try - { - buffer[0] = value; - await stream.WriteAsync(buffer, offset: 0, count: size, cancellationToken); - } - finally - { - ArrayPool.Shared.Return(buffer); - } - } - - public static async ValueTask WriteAsync(this Stream stream, int value, CancellationToken cancellationToken) - { - var size = sizeof(int); - var buffer = ArrayPool.Shared.Rent(minimumLength: size); - try - { - BinaryPrimitives.WriteInt32LittleEndian(buffer, value); - await stream.WriteAsync(buffer, offset: 0, count: size, cancellationToken); - } - finally - { - ArrayPool.Shared.Return(buffer); - } - } - - public static ValueTask WriteAsync(this Stream stream, Guid value, CancellationToken cancellationToken) - => stream.WriteAsync(value.ToByteArray(), cancellationToken); - - public static async ValueTask WriteByteArrayAsync(this Stream stream, byte[] value, CancellationToken cancellationToken) - { - await stream.WriteAsync(value.Length, cancellationToken); - await stream.WriteAsync(value, cancellationToken); - } - - public static async ValueTask WriteAsync(this Stream stream, int[] value, CancellationToken cancellationToken) - { - var size = sizeof(int) * (value.Length + 1); - var buffer = ArrayPool.Shared.Rent(minimumLength: size); - try - { - BinaryPrimitives.WriteInt32LittleEndian(buffer, value.Length); - for (int i = 0; i < value.Length; i++) - { - BinaryPrimitives.WriteInt32LittleEndian(buffer.AsSpan((i + 1) * sizeof(int), sizeof(int)), value[i]); - } - - await stream.WriteAsync(buffer, offset: 0, count: size, cancellationToken); - } - finally - { - ArrayPool.Shared.Return(buffer); - } - } - - public static async ValueTask WriteAsync(this Stream stream, string value, CancellationToken cancellationToken) - { - var bytes = Encoding.UTF8.GetBytes(value); - await stream.Write7BitEncodedIntAsync(bytes.Length, cancellationToken); - await stream.WriteAsync(bytes, cancellationToken); - } - - public static async ValueTask Write7BitEncodedIntAsync(this Stream stream, int value, CancellationToken cancellationToken) - { - uint uValue = (uint)value; - - while (uValue > 0x7Fu) - { - await stream.WriteAsync((byte)(uValue | ~0x7Fu), cancellationToken); - uValue >>= 7; - } - - await stream.WriteAsync((byte)uValue, cancellationToken); - } - - public static async ValueTask ReadBooleanAsync(this Stream stream, CancellationToken cancellationToken) - => await stream.ReadByteAsync(cancellationToken) != 0; - - public static async ValueTask ReadByteAsync(this Stream stream, CancellationToken cancellationToken) - { - int size = sizeof(byte); - var buffer = ArrayPool.Shared.Rent(minimumLength: size); - try - { - await ReadExactlyAsync(stream, buffer.AsMemory(0, size), cancellationToken); - return buffer[0]; - } - finally - { - ArrayPool.Shared.Return(buffer); - } - } - - public static async ValueTask ReadInt32Async(this Stream stream, CancellationToken cancellationToken) - { - int size = sizeof(int); - var buffer = ArrayPool.Shared.Rent(minimumLength: size); - try - { - await ReadExactlyAsync(stream, buffer.AsMemory(0, size), cancellationToken); - return BinaryPrimitives.ReadInt32LittleEndian(buffer); - } - finally - { - ArrayPool.Shared.Return(buffer); - } - } - - public static async ValueTask ReadGuidAsync(this Stream stream, CancellationToken cancellationToken) - { - const int size = 16; - var buffer = ArrayPool.Shared.Rent(minimumLength: size); - try - { - await ReadExactlyAsync(stream, buffer.AsMemory(0, size), cancellationToken); - return new Guid(buffer.AsSpan(0, size)); - } - finally - { - ArrayPool.Shared.Return(buffer); - } - } - - public static async ValueTask ReadByteArrayAsync(this Stream stream, CancellationToken cancellationToken) - { - var count = await stream.ReadInt32Async(cancellationToken); - if (count == 0) - { - return []; - } - - var bytes = new byte[count]; - await ReadExactlyAsync(stream, bytes, cancellationToken); - return bytes; - } - - public static async ValueTask ReadIntArrayAsync(this Stream stream, CancellationToken cancellationToken) - { - var count = await stream.ReadInt32Async(cancellationToken); - if (count == 0) - { - return []; - } - - var result = new int[count]; - int size = count * sizeof(int); - var buffer = ArrayPool.Shared.Rent(minimumLength: size); - try - { - await ReadExactlyAsync(stream, buffer.AsMemory(0, size), cancellationToken); - - for (var i = 0; i < count; i++) - { - result[i] = BinaryPrimitives.ReadInt32LittleEndian(buffer.AsSpan(i * sizeof(int))); - } - } - finally - { - ArrayPool.Shared.Return(buffer); - } - - return result; - } - - public static async ValueTask ReadStringAsync(this Stream stream, CancellationToken cancellationToken) - { - int size = await stream.Read7BitEncodedIntAsync(cancellationToken); - if (size < 0) - { - throw new InvalidDataException(); - } - - if (size == 0) - { - return string.Empty; - } - - var buffer = ArrayPool.Shared.Rent(minimumLength: size); - try - { - await ReadExactlyAsync(stream, buffer.AsMemory(0, size), cancellationToken); - return Encoding.UTF8.GetString(buffer.AsSpan(0, size)); - } - finally - { - ArrayPool.Shared.Return(buffer); - } - } - - public static async ValueTask Read7BitEncodedIntAsync(this Stream stream, CancellationToken cancellationToken) - { - const int MaxBytesWithoutOverflow = 4; - - uint result = 0; - byte b; - - for (int shift = 0; shift < MaxBytesWithoutOverflow * 7; shift += 7) - { - b = await stream.ReadByteAsync(cancellationToken); - result |= (b & 0x7Fu) << shift; - - if (b <= 0x7Fu) - { - return (int)result; - } - } - - // Read the 5th byte. Since we already read 28 bits, - // the value of this byte must fit within 4 bits (32 - 28), - // and it must not have the high bit set. - - b = await stream.ReadByteAsync(cancellationToken); - if (b > 0b_1111u) - { - throw new InvalidDataException(); - } - - result |= (uint)b << (MaxBytesWithoutOverflow * 7); - return (int)result; - } - - private static async ValueTask ReadExactlyAsync(this Stream stream, Memory buffer, CancellationToken cancellationToken) - { - int totalRead = 0; - while (totalRead < buffer.Length) - { - int read = await stream.ReadAsync(buffer.Slice(totalRead), cancellationToken).ConfigureAwait(false); - if (read == 0) - { - throw new EndOfStreamException(); - } - - totalRead += read; - } - - return totalRead; - } - } -} diff --git a/src/BuiltInTools/dotnet-watch/HotReload/ProjectLauncher.cs b/src/BuiltInTools/dotnet-watch/HotReload/ProjectLauncher.cs index 46a33b2b301d..c68073001705 100644 --- a/src/BuiltInTools/dotnet-watch/HotReload/ProjectLauncher.cs +++ b/src/BuiltInTools/dotnet-watch/HotReload/ProjectLauncher.cs @@ -1,8 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.Globalization; using Microsoft.Build.Graph; +using Microsoft.DotNet.HotReload; namespace Microsoft.DotNet.Watch; @@ -53,22 +55,17 @@ public EnvironmentOptions EnvironmentOptions { Executable = EnvironmentOptions.MuxerPath, WorkingDirectory = projectOptions.WorkingDirectory, - OnOutput = onOutput, - Arguments = [projectOptions.Command, "--no-build", .. projectOptions.CommandArguments] + OnOutput = onOutput }; var environmentBuilder = EnvironmentVariablesBuilder.FromCurrentEnvironment(); var namedPipeName = Guid.NewGuid().ToString(); - // Directives: - - // Variables: - foreach (var (name, value) in projectOptions.LaunchEnvironmentVariables) { // ignore dotnet-watch reserved variables -- these shouldn't be set by the project if (name.Equals(EnvironmentVariables.Names.AspNetCoreHostingStartupAssemblies, StringComparison.OrdinalIgnoreCase) || - name.Equals(EnvironmentVariables.Names.DotnetStartupHooks, StringComparison.OrdinalIgnoreCase)) + name.Equals(EnvironmentVariables.Names.DotNetStartupHooks, StringComparison.OrdinalIgnoreCase)) { continue; } @@ -85,30 +82,38 @@ public EnvironmentOptions EnvironmentOptions // expect DOTNET_MODIFIABLE_ASSEMBLIES to be set in the blazor-devserver process, even though we are not performing Hot Reload in this process. // The value is converted to DOTNET-MODIFIABLE-ASSEMBLIES header, which is in turn converted back to environment variable in Mono browser runtime loader: // https://github.com/dotnet/runtime/blob/342936c5a88653f0f622e9d6cb727a0e59279b31/src/mono/browser/runtime/loader/config.ts#L330 - environmentBuilder.SetDirective(EnvironmentVariables.Names.DotnetModifiableAssemblies, "debug"); + environmentBuilder.SetVariable(EnvironmentVariables.Names.DotNetModifiableAssemblies, "debug"); if (injectDeltaApplier) { - environmentBuilder.DotNetStartupHookDirective.Add(DeltaApplier.StartupHookPath); - environmentBuilder.SetDirective(EnvironmentVariables.Names.DotnetWatchHotReloadNamedPipeName, namedPipeName); - - // Do not ask agent to log to stdout until https://github.com/dotnet/sdk/issues/40484 is fixed. - // For now we need to set the env variable explicitly when we need to diagnose issue with the agent. - // Build targets might launch a process and read it's stdout. If the agent is loaded into such process and starts logging - // to stdout it might interfere with the expected output. - //if (context.Options.Verbose) - //{ - // environmentBuilder.SetVariable(EnvironmentVariables.Names.HotReloadDeltaClientLogMessages, "1"); - //} - - // TODO: workaround for https://github.com/dotnet/sdk/issues/40484 - var targetPath = projectNode.ProjectInstance.GetPropertyValue("RunCommand"); - environmentBuilder.SetVariable(EnvironmentVariables.Names.DotnetWatchHotReloadTargetProcessPath, targetPath); - Reporter.Verbose($"Target process is '{targetPath}'"); + // HotReload startup hook should be loaded before any other startup hooks: + environmentBuilder.DotNetStartupHooks.Insert(0, DeltaApplier.StartupHookPath); + + environmentBuilder.SetVariable(EnvironmentVariables.Names.DotNetWatchHotReloadNamedPipeName, namedPipeName); + + if (context.Options.Verbose) + { + environmentBuilder.SetVariable(EnvironmentVariables.Names.HotReloadDeltaClientLogMessages, "1"); + } + } + + var browserRefreshServer = await browserConnector.GetOrCreateBrowserRefreshServerAsync(projectNode, processSpec, environmentBuilder, projectOptions, cancellationToken); + + var arguments = new List() + { + projectOptions.Command, + "--no-build" + }; + + foreach (var (name, value) in environmentBuilder.GetEnvironment()) + { + arguments.Add("-e"); + arguments.Add($"{name}={value}"); } - var browserRefreshServer = await browserConnector.LaunchOrRefreshBrowserAsync(projectNode, processSpec, environmentBuilder, projectOptions, cancellationToken); - environmentBuilder.ConfigureProcess(processSpec); + arguments.AddRange(projectOptions.CommandArguments); + + processSpec.Arguments = arguments; var processReporter = new ProjectSpecificReporter(projectNode, Reporter); diff --git a/src/BuiltInTools/dotnet-watch/HotReload/RunningProject.cs b/src/BuiltInTools/dotnet-watch/HotReload/RunningProject.cs index 49d8268cf0cf..e24717b23d27 100644 --- a/src/BuiltInTools/dotnet-watch/HotReload/RunningProject.cs +++ b/src/BuiltInTools/dotnet-watch/HotReload/RunningProject.cs @@ -12,6 +12,7 @@ namespace Microsoft.DotNet.Watch internal sealed class RunningProject( ProjectGraphNode projectNode, ProjectOptions options, + EnvironmentOptions environmentOptions, DeltaApplier deltaApplier, IReporter reporter, BrowserRefreshServer? browserRefreshServer, @@ -21,13 +22,13 @@ internal sealed class RunningProject( CancellationTokenSource processTerminationSource, RestartOperation restartOperation, IReadOnlyList disposables, - Task> capabilityProvider) : IDisposable + ImmutableArray capabilities) : IDisposable { public readonly ProjectGraphNode ProjectNode = projectNode; public readonly ProjectOptions Options = options; public readonly BrowserRefreshServer? BrowserRefreshServer = browserRefreshServer; public readonly DeltaApplier DeltaApplier = deltaApplier; - public readonly Task> CapabilityProvider = capabilityProvider; + public readonly ImmutableArray Capabilities = capabilities; public readonly IReporter Reporter = reporter; public readonly Task RunningProcess = runningProcess; public readonly int ProcessId = processId; @@ -68,5 +69,24 @@ public async ValueTask WaitForProcessRunningAsync(CancellationToken cancellation { await DeltaApplier.WaitForProcessRunningAsync(cancellationToken); } + + public async ValueTask TerminateAsync(CancellationToken shutdownCancellationToken) + { + if (shutdownCancellationToken.IsCancellationRequested) + { + // Ctrl+C sent, wait for the process to exit + try + { + _ = await RunningProcess.WaitAsync(environmentOptions.ProcessCleanupTimeout, CancellationToken.None); + } + catch (TimeoutException) + { + // nop + } + } + + ProcessTerminationSource.Cancel(); + return await RunningProcess; + } } } diff --git a/src/BuiltInTools/dotnet-watch/HotReload/ScopedCssFileHandler.cs b/src/BuiltInTools/dotnet-watch/HotReload/ScopedCssFileHandler.cs index d9f241eb0fab..6c30ef91c0d9 100644 --- a/src/BuiltInTools/dotnet-watch/HotReload/ScopedCssFileHandler.cs +++ b/src/BuiltInTools/dotnet-watch/HotReload/ScopedCssFileHandler.cs @@ -4,7 +4,6 @@ using Microsoft.Build.Framework; using Microsoft.Build.Graph; -using Microsoft.TemplateEngine.Utils; namespace Microsoft.DotNet.Watch { @@ -81,12 +80,13 @@ public async ValueTask HandleFileChangesAsync(IReadOnlyList files, { if (browserConnector.TryGetRefreshServer(projectNode, out var browserRefreshServer)) { - reporter.Verbose($"[{projectNode.GetDisplayName()}] Refreshing browser."); - await HandleBrowserRefresh(browserRefreshServer, projectNode.ProjectInstance.FullPath, cancellationToken); - } - else - { - reporter.Verbose($"[{projectNode.GetDisplayName()}] No refresh server."); + // We'd like an accurate scoped css path, but this needs a lot of work to wire-up now. + // We'll handle this as part of https://github.com/dotnet/aspnetcore/issues/31217. + // For now, we'll make it look like some css file which would cause JS to update a + // single file if it's from the current project, or all locally hosted css files if it's a file from + // referenced project. + var relativeUrl = Path.GetFileNameWithoutExtension(projectNode.ProjectInstance.FullPath) + ".css"; + await browserRefreshServer.UpdateStaticAssetsAsync([relativeUrl], cancellationToken); } }); @@ -107,24 +107,5 @@ public async ValueTask HandleFileChangesAsync(IReadOnlyList files, reporter.Output("Hot reload of scoped css failed.", emoji: "🔥"); } } - - private static async Task HandleBrowserRefresh(BrowserRefreshServer browserRefreshServer, string containingProjectPath, CancellationToken cancellationToken) - { - // We'd like an accurate scoped css path, but this needs a lot of work to wire-up now. - // We'll handle this as part of https://github.com/dotnet/aspnetcore/issues/31217. - // For now, we'll make it look like some css file which would cause JS to update a - // single file if it's from the current project, or all locally hosted css files if it's a file from - // referenced project. - var cssFilePath = Path.GetFileNameWithoutExtension(containingProjectPath) + ".css"; - var message = new UpdateStaticFileMessage { Path = cssFilePath }; - await browserRefreshServer.SendJsonMessageAsync(message, cancellationToken); - } - - private readonly struct UpdateStaticFileMessage - { - public string Type => "UpdateStaticFile"; - - public string Path { get; init; } - } } } diff --git a/src/BuiltInTools/dotnet-watch/HotReload/StaticAssetUpdate.cs b/src/BuiltInTools/dotnet-watch/HotReload/StaticAssetUpdate.cs new file mode 100644 index 000000000000..8a2438ac1ea1 --- /dev/null +++ b/src/BuiltInTools/dotnet-watch/HotReload/StaticAssetUpdate.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.DotNet.Watch; + +internal readonly struct StaticAssetUpdate(string relativePath, string assemblyName, byte[] content, bool isApplicationProject) +{ + public string RelativePath { get; } = relativePath; + public string AssemblyName { get; } = assemblyName; + public byte[] Content { get; } = content; + public bool IsApplicationProject { get; } = isApplicationProject; +} diff --git a/src/BuiltInTools/dotnet-watch/HotReload/StaticFileHandler.cs b/src/BuiltInTools/dotnet-watch/HotReload/StaticFileHandler.cs index 05fde9ab4001..c89ee64fb86a 100644 --- a/src/BuiltInTools/dotnet-watch/HotReload/StaticFileHandler.cs +++ b/src/BuiltInTools/dotnet-watch/HotReload/StaticFileHandler.cs @@ -1,20 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. - -using System.Text.Json; -using System.Text.Json.Serialization; using Microsoft.Build.Graph; namespace Microsoft.DotNet.Watch { internal sealed class StaticFileHandler(IReporter reporter, ProjectNodeMap projectMap, BrowserConnector browserConnector) { - private static readonly JsonSerializerOptions s_jsonSerializerOptions = new(JsonSerializerDefaults.Web) - { - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull - }; - public async ValueTask HandleFileChangesAsync(IReadOnlyList files, CancellationToken cancellationToken) { var allFilesHandled = true; @@ -67,20 +59,11 @@ public async ValueTask HandleFileChangesAsync(IReadOnlyList f return allFilesHandled; } - var tasks = refreshRequests.Select(async request => - { - // Serialize all requests sent to a single server: - foreach (var path in request.Value) - { - reporter.Verbose($"Sending static file update request for asset '{path}'."); - var message = JsonSerializer.SerializeToUtf8Bytes(new UpdateStaticFileMessage { Path = path }, s_jsonSerializerOptions); - await request.Key.SendAsync(message, cancellationToken); - } - }); + var tasks = refreshRequests.Select(request => request.Key.UpdateStaticAssetsAsync(request.Value, cancellationToken).AsTask()); await Task.WhenAll(tasks).WaitAsync(cancellationToken); - reporter.Output("Hot Reload of static files succeeded.", emoji: "🔥"); + reporter.Output("Hot reload of static files succeeded.", emoji: "🔥"); return allFilesHandled; } diff --git a/src/BuiltInTools/dotnet-watch/HotReloadDotNetWatcher.cs b/src/BuiltInTools/dotnet-watch/HotReloadDotNetWatcher.cs index 4402c1fbf742..228b286bdccc 100644 --- a/src/BuiltInTools/dotnet-watch/HotReloadDotNetWatcher.cs +++ b/src/BuiltInTools/dotnet-watch/HotReloadDotNetWatcher.cs @@ -72,7 +72,6 @@ public override async Task WatchAsync(CancellationToken shutdownCancellationToke var waitForFileChangeBeforeRestarting = true; EvaluationResult? evaluationResult = null; RunningProject? rootRunningProject = null; - Task>? fileWatcherTask = null; IRuntimeProcessLauncher? runtimeProcessLauncher = null; CompilationHandler? compilationHandler = null; Action? fileChangedCallback = null; @@ -101,8 +100,7 @@ public override async Task WatchAsync(CancellationToken shutdownCancellationToke await using var browserConnector = new BrowserConnector(Context); var projectMap = new ProjectNodeMap(evaluationResult.ProjectGraph, Context.Reporter); - compilationHandler = new CompilationHandler(Context.Reporter); - var staticFileHandler = new StaticFileHandler(Context.Reporter, projectMap, browserConnector); + compilationHandler = new CompilationHandler(Context.Reporter, Context.EnvironmentOptions, shutdownCancellationToken); var scopedCssFileHandler = new ScopedCssFileHandler(Context.Reporter, projectMap, browserConnector); var projectLauncher = new ProjectLauncher(Context, projectMap, browserConnector, compilationHandler, iteration); var outputDirectories = GetProjectOutputDirectories(evaluationResult.ProjectGraph); @@ -111,7 +109,7 @@ public override async Task WatchAsync(CancellationToken shutdownCancellationToke var rootProjectNode = evaluationResult.ProjectGraph.GraphRoots.Single(); - runtimeProcessLauncher = runtimeProcessLauncherFactory?.TryCreate(rootProjectNode, projectLauncher, rootProjectOptions.BuildArguments); + runtimeProcessLauncher = runtimeProcessLauncherFactory?.TryCreate(rootProjectNode, projectLauncher, rootProjectOptions); if (runtimeProcessLauncher != null) { var launcherEnvironment = runtimeProcessLauncher.GetEnvironmentVariables(); @@ -255,7 +253,7 @@ void FileChangedCallback(ChangedPath change) var stopwatch = Stopwatch.StartNew(); HotReloadEventSource.Log.HotReloadStart(HotReloadEventSource.StartType.StaticHandler); - await staticFileHandler.HandleFileChangesAsync(changedFiles, iterationCancellationToken); + await compilationHandler.HandleStaticAssetChangesAsync(changedFiles, projectMap, iterationCancellationToken); HotReloadEventSource.Log.HotReloadEnd(HotReloadEventSource.StartType.StaticHandler); HotReloadEventSource.Log.HotReloadStart(HotReloadEventSource.StartType.ScopedCssHandler); @@ -264,7 +262,7 @@ void FileChangedCallback(ChangedPath change) HotReloadEventSource.Log.HotReloadStart(HotReloadEventSource.StartType.CompilationHandler); - var (projectsToRebuild, projectsToRestart) = await compilationHandler.HandleFileChangesAsync(restartPrompt: async (projectNames, cancellationToken) => + var (projectsToRebuild, projectsToRestart) = await compilationHandler.HandleManagedCodeChangesAsync(restartPrompt: async (projectNames, cancellationToken) => { if (_rudeEditRestartPrompt != null) { @@ -517,38 +515,24 @@ async Task> CaptureChangedFilesSnapshot(ImmutableDict await compilationHandler.TerminateNonRootProcessesAndDispose(CancellationToken.None); } - if (!rootProcessTerminationSource.IsCancellationRequested) + if (rootRunningProject != null) { - rootProcessTerminationSource.Cancel(); + await rootRunningProject.TerminateAsync(shutdownCancellationToken); } - try - { - // Wait for the root process to exit. - await Task.WhenAll(new[] { (Task?)rootRunningProject?.RunningProcess, fileWatcherTask }.Where(t => t != null)!); - } - catch (OperationCanceledException) when (!shutdownCancellationToken.IsCancellationRequested) + if (runtimeProcessLauncher != null) { - // nop + await runtimeProcessLauncher.DisposeAsync(); } - finally - { - fileWatcherTask = null; - if (runtimeProcessLauncher != null) - { - await runtimeProcessLauncher.DisposeAsync(); - } - - rootRunningProject?.Dispose(); + rootRunningProject?.Dispose(); - if (waitForFileChangeBeforeRestarting && - !shutdownCancellationToken.IsCancellationRequested && - !forceRestartCancellationSource.IsCancellationRequested) - { - using var shutdownOrForcedRestartSource = CancellationTokenSource.CreateLinkedTokenSource(shutdownCancellationToken, forceRestartCancellationSource.Token); - await WaitForFileChangeBeforeRestarting(fileWatcher, evaluationResult, shutdownOrForcedRestartSource.Token); - } + if (waitForFileChangeBeforeRestarting && + !shutdownCancellationToken.IsCancellationRequested && + !forceRestartCancellationSource.IsCancellationRequested) + { + using var shutdownOrForcedRestartSource = CancellationTokenSource.CreateLinkedTokenSource(shutdownCancellationToken, forceRestartCancellationSource.Token); + await WaitForFileChangeBeforeRestarting(fileWatcher, evaluationResult, shutdownOrForcedRestartSource.Token); } } } diff --git a/src/BuiltInTools/dotnet-watch/Internal/ConsoleReporter.cs b/src/BuiltInTools/dotnet-watch/Internal/ConsoleReporter.cs index d50f49e8b1cc..d539664fe43b 100644 --- a/src/BuiltInTools/dotnet-watch/Internal/ConsoleReporter.cs +++ b/src/BuiltInTools/dotnet-watch/Internal/ConsoleReporter.cs @@ -58,7 +58,8 @@ public void Report(MessageDescriptor descriptor, string prefix, object?[] args) switch (descriptor.Severity) { case MessageSeverity.Error: - WriteLine(console.Error, message, ConsoleColor.Red, descriptor.Emoji); + // Use stdout for error messages to preserve ordering with respect to other output. + WriteLine(console.Out, message, ConsoleColor.Red, descriptor.Emoji); break; case MessageSeverity.Warning: diff --git a/src/BuiltInTools/dotnet-watch/Internal/IReporter.cs b/src/BuiltInTools/dotnet-watch/Internal/IReporter.cs index e216f30af874..e00058d62221 100644 --- a/src/BuiltInTools/dotnet-watch/Internal/IReporter.cs +++ b/src/BuiltInTools/dotnet-watch/Internal/IReporter.cs @@ -75,7 +75,7 @@ public bool TryGetMessage(string? prefix, object?[] args, [NotNullWhen(true)] ou public static readonly MessageDescriptor IgnoringChangeInHiddenDirectory = new("Ignoring change in hidden directory '{0}': {1} '{2}'", "⌚", MessageSeverity.Verbose, s_id++); public static readonly MessageDescriptor IgnoringChangeInOutputDirectory = new("Ignoring change in output directory: {0} '{1}'", "⌚", MessageSeverity.Verbose, s_id++); public static readonly MessageDescriptor FileAdditionTriggeredReEvaluation = new("File addition triggered re-evaluation.", "⌚", MessageSeverity.Verbose, s_id++); - public static readonly MessageDescriptor NoHotReloadChangesToApply = new ("No C# changes to apply.", "⌚", MessageSeverity.Output, s_id++); + public static readonly MessageDescriptor NoCSharpChangesToApply = new ("No C# changes to apply.", "⌚", MessageSeverity.Output, s_id++); } internal interface IReporter diff --git a/src/BuiltInTools/dotnet-watch/Internal/PhysicalConsole.cs b/src/BuiltInTools/dotnet-watch/Internal/PhysicalConsole.cs index 3e3e14195dec..4a3bc0c17998 100644 --- a/src/BuiltInTools/dotnet-watch/Internal/PhysicalConsole.cs +++ b/src/BuiltInTools/dotnet-watch/Internal/PhysicalConsole.cs @@ -17,27 +17,7 @@ internal sealed class PhysicalConsole : IConsole public PhysicalConsole(TestFlags testFlags) { Console.OutputEncoding = Encoding.UTF8; - - bool readFromStdin; - if (testFlags.HasFlag(TestFlags.ReadKeyFromStdin)) - { - readFromStdin = true; - } - else - { - try - { - Console.TreatControlCAsInput = true; - readFromStdin = false; - } - catch - { - // fails when stdin is redirected - readFromStdin = true; - } - } - - _ = readFromStdin ? ListenToStandardInputAsync() : ListenToConsoleKeyPressAsync(); + _ = testFlags.HasFlag(TestFlags.ReadKeyFromStdin) ? ListenToStandardInputAsync() : ListenToConsoleKeyPressAsync(); } private async Task ListenToStandardInputAsync() @@ -73,7 +53,14 @@ private async Task ListenToStandardInputAsync() } private Task ListenToConsoleKeyPressAsync() - => Task.Factory.StartNew(() => + { + Console.CancelKeyPress += (s, e) => + { + e.Cancel = true; + KeyPressed?.Invoke(new ConsoleKeyInfo(CtrlC, ConsoleKey.C, shift: false, alt: false, control: true)); + }; + + return Task.Factory.StartNew(() => { while (true) { @@ -81,6 +68,7 @@ private Task ListenToConsoleKeyPressAsync() KeyPressed?.Invoke(key); } }, TaskCreationOptions.LongRunning); + } public TextWriter Error => Console.Error; public TextWriter Out => Console.Out; diff --git a/src/BuiltInTools/dotnet-watch/Properties/launchSettings.json b/src/BuiltInTools/dotnet-watch/Properties/launchSettings.json index de41cecc021a..356ddeb0689a 100644 --- a/src/BuiltInTools/dotnet-watch/Properties/launchSettings.json +++ b/src/BuiltInTools/dotnet-watch/Properties/launchSettings.json @@ -8,7 +8,8 @@ "DOTNET_WATCH_DEBUG_SDK_DIRECTORY": "$(RepoRoot)artifacts\\bin\\redist\\$(Configuration)\\dotnet\\sdk\\$(Version)", "DCP_IDE_REQUEST_TIMEOUT_SECONDS": "100000", "DCP_IDE_NOTIFICATION_TIMEOUT_SECONDS": "100000", - "DCP_IDE_NOTIFICATION_KEEPALIVE_SECONDS": "100000" + "DCP_IDE_NOTIFICATION_KEEPALIVE_SECONDS": "100000", + "DOTNET_WATCH_PROCESS_CLEANUP_TIMEOUT_MS": "0" } } } diff --git a/src/BuiltInTools/dotnet-watch/Utilities/ProjectGraphNodeExtensions.cs b/src/BuiltInTools/dotnet-watch/Utilities/ProjectGraphNodeExtensions.cs index d46945d500d9..42ff4703992c 100644 --- a/src/BuiltInTools/dotnet-watch/Utilities/ProjectGraphNodeExtensions.cs +++ b/src/BuiltInTools/dotnet-watch/Utilities/ProjectGraphNodeExtensions.cs @@ -36,6 +36,9 @@ public static bool IsNetCoreApp(this ProjectGraphNode projectNode, Version minVe public static string? GetOutputDirectory(this ProjectGraphNode projectNode) => projectNode.ProjectInstance.GetPropertyValue("TargetPath") is { Length: >0 } path ? Path.GetDirectoryName(Path.Combine(projectNode.ProjectInstance.Directory, path)) : null; + public static string GetAssemblyName(this ProjectGraphNode projectNode) + => projectNode.ProjectInstance.GetPropertyValue("TargetName"); + public static string? GetIntermediateOutputDirectory(this ProjectGraphNode projectNode) => projectNode.ProjectInstance.GetPropertyValue("IntermediateOutputPath") is { Length: >0 } path ? Path.Combine(projectNode.ProjectInstance.Directory, path) : null; diff --git a/src/BuiltInTools/dotnet-watch/dotnet-watch.csproj b/src/BuiltInTools/dotnet-watch/dotnet-watch.csproj index 3e507fffa76c..8e550042fc52 100644 --- a/src/BuiltInTools/dotnet-watch/dotnet-watch.csproj +++ b/src/BuiltInTools/dotnet-watch/dotnet-watch.csproj @@ -1,5 +1,6 @@  + @@ -38,39 +39,21 @@ + + - + - + - + - + - + diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/FileManipulation/FileUtil.cs b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/FileManipulation/FileUtil.cs deleted file mode 100644 index 57eda12b7a4d..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/FileManipulation/FileUtil.cs +++ /dev/null @@ -1,154 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// FileUtil.cs -// -// Author: -// Lluis Sanchez Gual -// -// Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#nullable disable - -namespace Microsoft.DotNet.Cli.Sln.Internal.FileManipulation -{ - internal static class FileUtil - { - internal static TextFormatInfo GetTextFormatInfo(string file) - { - var info = new TextFormatInfo(); - - string newLine = null; - Encoding encoding; - - using (FileStream fs = File.OpenRead(file)) - { - byte[] buf = new byte[1024]; - int nread, i; - - if ((nread = fs.Read(buf, 0, buf.Length)) <= 0) - { - return info; - } - - if (TryParse(buf, nread, out encoding)) - { - i = encoding.GetPreamble().Length; - } - else - { - encoding = null; - i = 0; - } - - do - { - while (i < nread) - { - if (buf[i] == '\r') - { - newLine = "\r\n"; - break; - } - else if (buf[i] == '\n') - { - newLine = "\n"; - break; - } - - i++; - } - - if (newLine == null) - { - if ((nread = fs.Read(buf, 0, buf.Length)) <= 0) - { - newLine = "\n"; - break; - } - - i = 0; - } - } while (newLine == null); - - info.EndsWithEmptyLine = fs.Seek(-1, SeekOrigin.End) > 0 && fs.ReadByte() == (int)'\n'; - info.NewLine = newLine; - info.Encoding = encoding; - return info; - } - } - - private static bool TryParse(byte[] buffer, int available, out Encoding encoding) - { - if (buffer.Length >= 2) - { - for (int i = 0; i < table.Length; i++) - { - bool matched = true; - - if (available < table[i].GetPreamble().Length) - { - continue; - } - - for (int j = 0; j < table[i].GetPreamble().Length; j++) - { - if (buffer[j] != table[i].GetPreamble()[j]) - { - matched = false; - break; - } - } - - if (matched) - { - encoding = table[i]; - return true; - } - } - } - - encoding = null; - - return false; - } - - private static readonly Encoding[] table = new[] { - Encoding.UTF8, - Encoding.UTF32, - Encoding.ASCII, - }; - } - - internal class TextFormatInfo - { - public TextFormatInfo() - { - NewLine = Environment.NewLine; - Encoding = null; - EndsWithEmptyLine = true; - } - - public string NewLine { get; set; } - public Encoding Encoding { get; set; } - public bool EndsWithEmptyLine { get; set; } - } -} diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/LocalizableStrings.resx b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/LocalizableStrings.resx deleted file mode 100644 index 524b72423138..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/LocalizableStrings.resx +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Invalid format in line {0}: {1} - - - Project section is missing '{0}' when parsing the line starting at position {1} - - - Property set is missing '{0}' - - - Global section specified more than once - - - Global section not closed - - - File header is missing version - - - Expected file header not found - - - Project section not closed - - - Invalid section type: {0} - - - Section id missing - - - Closing section tag not found - - diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/Microsoft.DotNet.Cli.Sln.Internal.csproj b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/Microsoft.DotNet.Cli.Sln.Internal.csproj deleted file mode 100644 index 1618b780490d..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/Microsoft.DotNet.Cli.Sln.Internal.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - SLN file reader/writer - $(SdkTargetFramework) - portable - Microsoft.DotNet.Cli.Sln.Internal - MicrosoftAspNetCore - true - true - true - - - - - - - - - - diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/ProjectTypeGuids.cs b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/ProjectTypeGuids.cs deleted file mode 100644 index 5db6beb30ed7..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/ProjectTypeGuids.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace Microsoft.DotNet.Cli.Sln.Internal -{ - public static class ProjectTypeGuids - { - public const string CSharpProjectTypeGuid = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"; - public const string FSharpProjectTypeGuid = "{F2A71F9B-5D33-465A-A702-920D77279786}"; - public const string VBProjectTypeGuid = "{F184B08F-C81C-45F6-A57F-5ABD9991F28F}"; - public const string SolutionFolderGuid = "{2150E333-8FDC-42A3-9474-1A3956D46DE8}"; - public const string SharedProjectGuid = "{D954291E-2A0B-460D-934E-DC6B0785DB48}"; - } -} diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/Properties/AssemblyInfo.cs b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/Properties/AssemblyInfo.cs deleted file mode 100644 index 98cdd1d19b73..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Microsoft.DotNet.Cli.Sln.Internal.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -[assembly: InternalsVisibleTo("dotnet-sln.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] - - diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/SlnFile.cs b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/SlnFile.cs deleted file mode 100644 index 88f246b9e940..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/SlnFile.cs +++ /dev/null @@ -1,1201 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// -// SlnFile.cs -// -// Author: -// Lluis Sanchez Gual -// -// Copyright (c) 2016 Xamarin, Inc (http://www.xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#nullable disable - -using System.Collections; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.Globalization; -using System.Reflection; -using Microsoft.DotNet.Cli.Sln.Internal.FileManipulation; -using Microsoft.DotNet.Tools.Common; - -namespace Microsoft.DotNet.Cli.Sln.Internal -{ - public class SlnFile - { - private SlnProjectCollection _projects = new(); - private SlnSectionCollection _sections = new(); - private SlnPropertySet _metadata = new(true); - private int _prefixBlankLines = 1; - private TextFormatInfo _format = new(); - - public string FormatVersion { get; set; } - public string ProductDescription { get; set; } - - public string VisualStudioVersion - { - get { return _metadata.GetValue("VisualStudioVersion"); } - set { _metadata.SetValue("VisualStudioVersion", value); } - } - - public string MinimumVisualStudioVersion - { - get { return _metadata.GetValue("MinimumVisualStudioVersion"); } - set { _metadata.SetValue("MinimumVisualStudioVersion", value); } - } - - public string BaseDirectory - { - get { return Path.GetDirectoryName(FullPath); } - } - - public string FullPath { get; set; } - - public SlnPropertySet SolutionConfigurationsSection - { - get - { - return _sections - .GetOrCreateSection("SolutionConfigurationPlatforms", SlnSectionType.PreProcess) - .Properties; - } - } - - public SlnPropertySetCollection ProjectConfigurationsSection - { - get - { - return _sections - .GetOrCreateSection("ProjectConfigurationPlatforms", SlnSectionType.PostProcess) - .NestedPropertySets; - } - } - - public SlnSectionCollection Sections - { - get { return _sections; } - } - - public SlnProjectCollection Projects - { - get { return _projects; } - } - - public SlnFile() - { - _projects.ParentFile = this; - _sections.ParentFile = this; - } - - public static SlnFile Read(string file) - { - SlnFile slnFile = new() - { - FullPath = Path.GetFullPath(file), - _format = FileUtil.GetTextFormatInfo(file) - }; - - using (var sr = new StreamReader(new FileStream(file, FileMode.Open, FileAccess.Read))) - { - slnFile.Read(sr); - } - - return slnFile; - } - - private void Read(TextReader reader) - { - const string HeaderPrefix = "Microsoft Visual Studio Solution File, Format Version"; - - string line; - int curLineNum = 0; - bool globalFound = false; - bool productRead = false; - - while ((line = reader.ReadLine()) != null) - { - curLineNum++; - line = line.Trim(); - if (line.StartsWith(HeaderPrefix, StringComparison.Ordinal)) - { - if (line.Length <= HeaderPrefix.Length) - { - throw new InvalidSolutionFormatException( - curLineNum, - LocalizableStrings.FileHeaderMissingVersionError); - } - - FormatVersion = line.Substring(HeaderPrefix.Length).Trim(); - _prefixBlankLines = curLineNum - 1; - } - if (line.StartsWith("# ", StringComparison.Ordinal)) - { - if (!productRead) - { - productRead = true; - ProductDescription = line.Substring(2); - } - } - else if (line.StartsWith("Project", StringComparison.Ordinal)) - { - SlnProject p = new(); - p.Read(reader, line, ref curLineNum); - _projects.Add(p); - } - else if (line == "Global") - { - if (globalFound) - { - throw new InvalidSolutionFormatException( - curLineNum, - LocalizableStrings.GlobalSectionMoreThanOnceError); - } - globalFound = true; - while ((line = reader.ReadLine()) != null) - { - curLineNum++; - line = line.Trim(); - if (line == "EndGlobal") - { - break; - } - else if (line.StartsWith("GlobalSection", StringComparison.Ordinal)) - { - var sec = new SlnSection(); - sec.Read(reader, line, ref curLineNum); - _sections.Add(sec); - } - else // Ignore text that's out of place - { - continue; - } - } - if (line == null) - { - throw new InvalidSolutionFormatException( - curLineNum, - LocalizableStrings.GlobalSectionNotClosedError); - } - } - else if (line.IndexOf('=') != -1) - { - _metadata.ReadLine(line, curLineNum); - } - } - if (FormatVersion == null) - { - throw new InvalidSolutionFormatException(LocalizableStrings.FileHeaderMissingError); - } - } - - public void Write(string file = null) - { - if (!string.IsNullOrEmpty(file)) - { - FullPath = Path.GetFullPath(file); - } - var sw = new StringWriter(); - Write(sw); - File.WriteAllText(FullPath, sw.ToString(), Encoding.UTF8); - } - - private void Write(TextWriter writer) - { - writer.NewLine = _format.NewLine; - for (int n = 0; n < _prefixBlankLines; n++) - { - writer.WriteLine(); - } - writer.WriteLine("Microsoft Visual Studio Solution File, Format Version " + FormatVersion); - writer.WriteLine("# " + ProductDescription); - - _metadata.Write(writer); - - foreach (var p in _projects) - { - p.Write(writer); - } - - writer.WriteLine("Global"); - foreach (SlnSection s in _sections) - { - s.Write(writer, "GlobalSection"); - } - writer.WriteLine("EndGlobal"); - } - } - - public class SlnProject - { - private SlnSectionCollection _sections = new(); - - private SlnFile _parentFile; - - public SlnFile ParentFile - { - get - { - return _parentFile; - } - internal set - { - _parentFile = value; - _sections.ParentFile = _parentFile; - } - } - - public string Id { get; set; } - public string TypeGuid { get; set; } - public string Name { get; set; } - - private string _filePath; - public string FilePath - { - get - { - return _filePath; - } - set - { - _filePath = PathUtility.RemoveExtraPathSeparators( - PathUtility.GetPathWithDirectorySeparator(value)); - } - } - - public int Line { get; private set; } - internal bool Processed { get; set; } - - public SlnSectionCollection Sections - { - get { return _sections; } - } - - public SlnSection Dependencies - { - get - { - return _sections.GetSection("ProjectDependencies", SlnSectionType.PostProcess); - } - } - - internal void Read(TextReader reader, string line, ref int curLineNum) - { - Line = curLineNum; - - int n = 0; - FindNext(curLineNum, line, ref n, '('); - n++; - FindNext(curLineNum, line, ref n, '"'); - int n2 = n + 1; - FindNext(curLineNum, line, ref n2, '"'); - TypeGuid = line.Substring(n + 1, n2 - n - 1); - - n = n2 + 1; - FindNext(curLineNum, line, ref n, ')'); - FindNext(curLineNum, line, ref n, '='); - - FindNext(curLineNum, line, ref n, '"'); - n2 = n + 1; - FindNext(curLineNum, line, ref n2, '"'); - Name = line.Substring(n + 1, n2 - n - 1); - - n = n2 + 1; - FindNext(curLineNum, line, ref n, ','); - FindNext(curLineNum, line, ref n, '"'); - n2 = n + 1; - FindNext(curLineNum, line, ref n2, '"'); - FilePath = line.Substring(n + 1, n2 - n - 1); - - n = n2 + 1; - FindNext(curLineNum, line, ref n, ','); - FindNext(curLineNum, line, ref n, '"'); - n2 = n + 1; - FindNext(curLineNum, line, ref n2, '"'); - Id = line.Substring(n + 1, n2 - n - 1); - - while ((line = reader.ReadLine()) != null) - { - curLineNum++; - line = line.Trim(); - if (line == "EndProject") - { - return; - } - if (line.StartsWith("ProjectSection", StringComparison.Ordinal)) - { - if (_sections == null) - { - _sections = new SlnSectionCollection(); - } - var sec = new SlnSection(); - _sections.Add(sec); - sec.Read(reader, line, ref curLineNum); - } - } - - throw new InvalidSolutionFormatException( - curLineNum, - LocalizableStrings.ProjectSectionNotClosedError); - } - - private void FindNext(int ln, string line, ref int i, char c) - { - var inputIndex = i; - i = line.IndexOf(c, i); - if (i == -1) - { - throw new InvalidSolutionFormatException( - ln, - string.Format(LocalizableStrings.ProjectParsingErrorFormatString, c, inputIndex)); - } - } - - internal void Write(TextWriter writer) - { - writer.Write("Project(\""); - writer.Write(TypeGuid); - writer.Write("\") = \""); - writer.Write(Name); - writer.Write("\", \""); - writer.Write(PathUtility.GetPathWithBackSlashes(FilePath)); - writer.Write("\", \""); - writer.Write(Id); - writer.WriteLine("\""); - if (_sections != null) - { - foreach (SlnSection s in _sections) - { - s.Write(writer, "ProjectSection"); - } - } - writer.WriteLine("EndProject"); - } - } - - public class SlnSection - { - private SlnPropertySetCollection _nestedPropertySets; - private SlnPropertySet _properties; - private List _sectionLines; - private int _baseIndex; - - public string Id { get; set; } - public int Line { get; private set; } - - internal bool Processed { get; set; } - - public SlnFile ParentFile { get; internal set; } - - public bool IsEmpty - { - get - { - return (_properties == null || _properties.Count == 0) && - (_nestedPropertySets == null || _nestedPropertySets.All(t => t.IsEmpty)) && - (_sectionLines == null || _sectionLines.Count == 0); - } - } - - /// - /// If true, this section won't be written to the file if it is empty - /// - /// true if skip if empty; otherwise, false. - public bool SkipIfEmpty { get; set; } - - public void Clear() - { - _properties = null; - _nestedPropertySets = null; - _sectionLines = null; - } - - public SlnPropertySet Properties - { - get - { - if (_properties == null) - { - _properties = new SlnPropertySet - { - ParentSection = this - }; - if (_sectionLines != null) - { - foreach (var line in _sectionLines) - { - _properties.ReadLine(line, Line); - } - _sectionLines = null; - } - } - return _properties; - } - } - - public SlnPropertySetCollection NestedPropertySets - { - get - { - if (_nestedPropertySets == null) - { - _nestedPropertySets = new SlnPropertySetCollection(this); - if (_sectionLines != null) - { - LoadPropertySets(); - } - } - return _nestedPropertySets; - } - } - - public void SetContent(IEnumerable> lines) - { - _sectionLines = new List(lines.Select(p => p.Key + " = " + p.Value)); - _properties = null; - _nestedPropertySets = null; - } - - public IEnumerable> GetContent() - { - if (_sectionLines != null) - { - return _sectionLines.Select(li => - { - int i = li.IndexOf('='); - if (i != -1) - { - return new KeyValuePair(li.Substring(0, i).Trim(), li.Substring(i + 1).Trim()); - } - else - { - return new KeyValuePair(li.Trim(), ""); - } - }); - } - else - { - return new KeyValuePair[0]; - } - } - - public SlnSectionType SectionType { get; set; } - - private SlnSectionType ToSectionType(int curLineNum, string s) - { - if (s == "preSolution" || s == "preProject") - { - return SlnSectionType.PreProcess; - } - if (s == "postSolution" || s == "postProject") - { - return SlnSectionType.PostProcess; - } - throw new InvalidSolutionFormatException( - curLineNum, - string.Format(LocalizableStrings.InvalidSectionTypeError, s)); - } - - private string FromSectionType(bool isProjectSection, SlnSectionType type) - { - if (type == SlnSectionType.PreProcess) - { - return isProjectSection ? "preProject" : "preSolution"; - } - else - { - return isProjectSection ? "postProject" : "postSolution"; - } - } - - internal void Read(TextReader reader, string line, ref int curLineNum) - { - Line = curLineNum; - int k = line.IndexOf('('); - if (k == -1) - { - throw new InvalidSolutionFormatException( - curLineNum, - LocalizableStrings.SectionIdMissingError); - } - var tag = line.Substring(0, k).Trim(); - var k2 = line.IndexOf(')', k); - if (k2 == -1) - { - throw new InvalidSolutionFormatException( - curLineNum, - LocalizableStrings.SectionIdMissingError); - } - Id = line.Substring(k + 1, k2 - k - 1); - - k = line.IndexOf('=', k2); - SectionType = ToSectionType(curLineNum, line.Substring(k + 1).Trim()); - - var endTag = "End" + tag; - - _sectionLines = new List(); - _baseIndex = ++curLineNum; - while ((line = reader.ReadLine()) != null) - { - curLineNum++; - line = line.Trim(); - if (line == endTag) - { - break; - } - _sectionLines.Add(line); - } - if (line == null) - { - throw new InvalidSolutionFormatException( - curLineNum, - LocalizableStrings.ClosingSectionTagNotFoundError); - } - } - - private void LoadPropertySets() - { - if (_sectionLines != null) - { - SlnPropertySet curSet = null; - for (int n = 0; n < _sectionLines.Count; n++) - { - var line = _sectionLines[n]; - if (string.IsNullOrEmpty(line.Trim())) - { - continue; - } - var i = line.IndexOf('.'); - if (i == -1) - { - throw new InvalidSolutionFormatException( - _baseIndex + n, - string.Format(LocalizableStrings.InvalidPropertySetFormatString, '.')); - } - var id = line.Substring(0, i); - if (curSet == null || id != curSet.Id) - { - curSet = new SlnPropertySet(id); - _nestedPropertySets.Add(curSet); - } - curSet.ReadLine(line.Substring(i + 1), _baseIndex + n); - } - _sectionLines = null; - } - } - - internal void Write(TextWriter writer, string sectionTag) - { - if (SkipIfEmpty && IsEmpty) - { - return; - } - - writer.Write("\t"); - writer.Write(sectionTag); - writer.Write('('); - writer.Write(Id); - writer.Write(") = "); - writer.WriteLine(FromSectionType(sectionTag == "ProjectSection", SectionType)); - if (_sectionLines != null) - { - foreach (var l in _sectionLines) - { - writer.WriteLine("\t\t" + l); - } - } - else if (_properties != null) - { - _properties.Write(writer); - } - else if (_nestedPropertySets != null) - { - foreach (var ps in _nestedPropertySets) - { - ps.Write(writer); - } - } - writer.WriteLine("\tEnd" + sectionTag); - } - } - - /// - /// A collection of properties - /// - public class SlnPropertySet : IDictionary - { - private OrderedDictionary _values = new(); - private bool _isMetadata; - - internal bool Processed { get; set; } - - public SlnFile ParentFile - { - get { return ParentSection != null ? ParentSection.ParentFile : null; } - } - - public SlnSection ParentSection { get; set; } - - /// - /// Text file line of this section in the original file - /// - /// The line. - public int Line { get; private set; } - - internal SlnPropertySet() - { - } - - /// - /// Creates a new property set with the specified ID - /// - /// Identifier. - public SlnPropertySet(string id) - { - Id = id; - } - - internal SlnPropertySet(bool isMetadata) - { - _isMetadata = isMetadata; - } - - public bool IsEmpty - { - get - { - return _values.Count == 0; - } - } - - internal void ReadLine(string line, int currentLine) - { - if (Line == 0) - { - Line = currentLine; - } - int k = line.IndexOf('='); - if (k != -1) - { - var name = line.Substring(0, k).Trim(); - var val = line.Substring(k + 1).Trim(); - _values[name] = val; - } - else - { - line = line.Trim(); - if (!string.IsNullOrWhiteSpace(line)) - { - _values.Add(line, null); - } - } - } - - internal void Write(TextWriter writer) - { - foreach (DictionaryEntry e in _values) - { - if (!_isMetadata) - { - writer.Write("\t\t"); - } - if (Id != null) - { - writer.Write(Id + "."); - } - writer.WriteLine(e.Key + " = " + e.Value); - } - } - - public string Id { get; private set; } - - public string GetValue(string name, string defaultValue = null) - { - string res; - if (TryGetValue(name, out res)) - { - return res; - } - else - { - return defaultValue; - } - } - - public T GetValue(string name) - { - return (T)GetValue(name, typeof(T), default(T)); - } - - public T GetValue(string name, T defaultValue) - { - return (T)GetValue(name, typeof(T), defaultValue); - } - - public object GetValue(string name, Type t, object defaultValue) - { - string val; - if (TryGetValue(name, out val)) - { - if (t == typeof(bool)) - { - return (object)val.Equals("true", StringComparison.OrdinalIgnoreCase); - } - if (t.GetTypeInfo().IsEnum) - { - return Enum.Parse(t, val, true); - } - if (t.GetTypeInfo().IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)) - { - var at = t.GetTypeInfo().GetGenericArguments()[0]; - if (string.IsNullOrEmpty(val)) - { - return null; - } - return Convert.ChangeType(val, at, CultureInfo.InvariantCulture); - - } - return Convert.ChangeType(val, t, CultureInfo.InvariantCulture); - } - else - { - return defaultValue; - } - } - - public void SetValue(string name, string value, string defaultValue = null, bool preserveExistingCase = false) - { - if (value == null && defaultValue == "") - { - value = ""; - } - if (value == defaultValue) - { - // if the value is default, only remove the property if it was not already the default - // to avoid unnecessary project file churn - string res; - if (TryGetValue(name, out res) && - !string.Equals(defaultValue ?? "", - res, preserveExistingCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)) - { - Remove(name); - } - return; - } - string currentValue; - if (preserveExistingCase && TryGetValue(name, out currentValue) && - string.Equals(value, currentValue, StringComparison.OrdinalIgnoreCase)) - { - return; - } - _values[name] = value; - } - - public void SetValue(string name, object value, object defaultValue = null) - { - var isDefault = Equals(value, defaultValue); - if (isDefault) - { - // if the value is default, only remove the property if it was not already the default - // to avoid unnecessary project file churn - if (ContainsKey(name) && (defaultValue == null || - !Equals(defaultValue, GetValue(name, defaultValue.GetType(), null)))) - { - Remove(name); - } - return; - } - - if (value is bool) - { - _values[name] = (bool)value ? "TRUE" : "FALSE"; - } - else - { - _values[name] = Convert.ToString(value, CultureInfo.InvariantCulture); - } - } - - void IDictionary.Add(string key, string value) - { - SetValue(key, value); - } - - public bool ContainsKey(string key) - { - return _values.Contains(key); - } - - public bool Remove(string key) - { - var wasThere = _values.Contains(key); - _values.Remove(key); - return wasThere; - } - - public bool TryGetValue(string key, out string value) - { - value = (string)_values[key]; - return value != null; - } - - public string this[string index] - { - get - { - return (string)_values[index]; - } - set - { - _values[index] = value; - } - } - - public ICollection Values - { - get - { - return _values.Values.Cast().ToList(); - } - } - - public ICollection Keys - { - get { return _values.Keys.Cast().ToList(); } - } - - void ICollection>.Add(KeyValuePair item) - { - SetValue(item.Key, item.Value); - } - - public void Clear() - { - _values.Clear(); - } - - internal void ClearExcept(HashSet keys) - { - foreach (var k in _values.Keys.Cast().Except(keys).ToArray()) - { - _values.Remove(k); - } - } - - bool ICollection>.Contains(KeyValuePair item) - { - var val = GetValue(item.Key); - return val == item.Value; - } - - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - foreach (DictionaryEntry de in _values) - { - array[arrayIndex++] = new KeyValuePair((string)de.Key, (string)de.Value); - } - } - - bool ICollection>.Remove(KeyValuePair item) - { - if (((ICollection>)this).Contains(item)) - { - Remove(item.Key); - return true; - } - else - { - return false; - } - } - - public int Count - { - get - { - return _values.Count; - } - } - - internal void SetLines(IEnumerable> lines) - { - _values.Clear(); - foreach (var line in lines) - { - _values[line.Key] = line.Value; - } - } - - bool ICollection>.IsReadOnly - { - get - { - return false; - } - } - - public IEnumerator> GetEnumerator() - { - foreach (DictionaryEntry de in _values) - { - yield return new KeyValuePair((string)de.Key, (string)de.Value); - } - } - - IEnumerator IEnumerable.GetEnumerator() - { - foreach (DictionaryEntry de in _values) - { - yield return new KeyValuePair((string)de.Key, (string)de.Value); - } - } - } - - public class SlnProjectCollection : Collection - { - private SlnFile _parentFile; - - internal SlnFile ParentFile - { - get - { - return _parentFile; - } - set - { - _parentFile = value; - foreach (var it in this) - { - it.ParentFile = _parentFile; - } - } - } - - public SlnProject GetProject(string id) - { - return this.FirstOrDefault(s => s.Id == id); - } - - public SlnProject GetOrCreateProject(string id) - { - var p = this.FirstOrDefault(s => s.Id.Equals(id, StringComparison.OrdinalIgnoreCase)); - if (p == null) - { - p = new SlnProject { Id = id }; - Add(p); - } - return p; - } - - protected override void InsertItem(int index, SlnProject item) - { - base.InsertItem(index, item); - item.ParentFile = ParentFile; - } - - protected override void SetItem(int index, SlnProject item) - { - base.SetItem(index, item); - item.ParentFile = ParentFile; - } - - protected override void RemoveItem(int index) - { - var it = this[index]; - it.ParentFile = null; - base.RemoveItem(index); - } - - protected override void ClearItems() - { - foreach (var it in this) - { - it.ParentFile = null; - } - base.ClearItems(); - } - } - - public class SlnSectionCollection : Collection - { - private SlnFile _parentFile; - - internal SlnFile ParentFile - { - get - { - return _parentFile; - } - set - { - _parentFile = value; - foreach (var it in this) - { - it.ParentFile = _parentFile; - } - } - } - - public SlnSection GetSection(string id) - { - return this.FirstOrDefault(s => s.Id == id); - } - - public SlnSection GetSection(string id, SlnSectionType sectionType) - { - return this.FirstOrDefault(s => s.Id == id && s.SectionType == sectionType); - } - - public SlnSection GetOrCreateSection(string id, SlnSectionType sectionType) - { - if (id == null) - { - throw new ArgumentNullException("id"); - } - var sec = this.FirstOrDefault(s => s.Id == id); - if (sec == null) - { - sec = new SlnSection - { - Id = id, - SectionType = sectionType - }; - Add(sec); - } - return sec; - } - - public void RemoveSection(string id) - { - if (id == null) - { - throw new ArgumentNullException("id"); - } - var s = GetSection(id); - if (s != null) - { - Remove(s); - } - } - - protected override void InsertItem(int index, SlnSection item) - { - base.InsertItem(index, item); - item.ParentFile = ParentFile; - } - - protected override void SetItem(int index, SlnSection item) - { - base.SetItem(index, item); - item.ParentFile = ParentFile; - } - - protected override void RemoveItem(int index) - { - var it = this[index]; - it.ParentFile = null; - base.RemoveItem(index); - } - - protected override void ClearItems() - { - foreach (var it in this) - { - it.ParentFile = null; - } - base.ClearItems(); - } - } - - public class SlnPropertySetCollection : Collection - { - private SlnSection _parentSection; - - internal SlnPropertySetCollection(SlnSection parentSection) - { - _parentSection = parentSection; - } - - public SlnPropertySet GetPropertySet(string id, bool ignoreCase = false) - { - var sc = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - return this.FirstOrDefault(s => s.Id.Equals(id, sc)); - } - - public SlnPropertySet GetOrCreatePropertySet(string id, bool ignoreCase = false) - { - var ps = GetPropertySet(id, ignoreCase); - if (ps == null) - { - ps = new SlnPropertySet(id); - Add(ps); - } - return ps; - } - - protected override void InsertItem(int index, SlnPropertySet item) - { - base.InsertItem(index, item); - item.ParentSection = _parentSection; - } - - protected override void SetItem(int index, SlnPropertySet item) - { - base.SetItem(index, item); - item.ParentSection = _parentSection; - } - - protected override void RemoveItem(int index) - { - var it = this[index]; - it.ParentSection = null; - base.RemoveItem(index); - } - - protected override void ClearItems() - { - foreach (var it in this) - { - it.ParentSection = null; - } - base.ClearItems(); - } - } - - public class InvalidSolutionFormatException : Exception - { - public InvalidSolutionFormatException(string details) - : base(details) - { - } - - public InvalidSolutionFormatException(int line, string details) - : base(string.Format(LocalizableStrings.ErrorMessageFormatString, line, details)) - { - } - } - - public enum SlnSectionType - { - PreProcess, - PostProcess - } -} - diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.cs.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.cs.xlf deleted file mode 100644 index 5d973eb64247..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.cs.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - Několikrát zadaný globální oddíl - - - - Global section not closed - Neuzavřený globální oddíl - - - - Expected file header not found - Nenalezena očekávaná hlavička souboru - - - - Project section not closed - Neuzavřený oddíl projektu - - - - Invalid section type: {0} - Neplatný typ oddílu: {0} - - - - Section id missing - Chybí ID oddílu - - - - Closing section tag not found - Nenalezena koncová značka oddílu - - - - Invalid format in line {0}: {1} - Neplatný formát na řádku {0}: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - V oddíle projektu chybí {0}, když analýza řádku začíná na pozici {1}. - - - - Property set is missing '{0}' - V sadě vlastností chybí {0}. - - - - File header is missing version - Chybějící verze v hlavičce souboru - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.de.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.de.xlf deleted file mode 100644 index 5e6f488308ac..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.de.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - Globaler Abschnitt mehrmals angegeben - - - - Global section not closed - Globaler Abschnitt nicht geschlossen - - - - Expected file header not found - Erwarteter Dateiheader nicht gefunden. - - - - Project section not closed - Projektabschnitt nicht geschlossen - - - - Invalid section type: {0} - Ungültiger Abschnittstyp: {0} - - - - Section id missing - Abschnitts-ID fehlt - - - - Closing section tag not found - Schließendes Abschnittstag nicht gefunden - - - - Invalid format in line {0}: {1} - Ungültiges Format in Zeile {0}: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - Im Projektabschnitt fehlt "{0}" beim Analysieren des Zeilenbeginns in Position {1} - - - - Property set is missing '{0}' - Im Eigenschaftensatz fehlt "{0}" - - - - File header is missing version - Der Dateiheader enthält keine Version. - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.es.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.es.xlf deleted file mode 100644 index 365664c207aa..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.es.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - Sección global especificada más de una vez - - - - Global section not closed - Sección global no cerrada - - - - Expected file header not found - No se encontró el encabezado de archivo esperado - - - - Project section not closed - Sección de proyecto no cerrada - - - - Invalid section type: {0} - Tipo de sección no válido: {0} - - - - Section id missing - Id. de sección omitido - - - - Closing section tag not found - No se encuentra la etiqueta de cierre de la sección - - - - Invalid format in line {0}: {1} - Formato no válido en línea {0}: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - Falta la sección del proyecto "{0}" al analizar la línea que inicia en la posición {1} - - - - Property set is missing '{0}' - A la propiedad establecida le falta "{0}" - - - - File header is missing version - Falta la versión del encabezado de archivo - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.fr.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.fr.xlf deleted file mode 100644 index dd00afbe039e..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.fr.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - Section Global spécifiée plusieurs fois - - - - Global section not closed - Section Global non fermée - - - - Expected file header not found - En-tête de fichier attendu introuvable - - - - Project section not closed - Section Project non fermée - - - - Invalid section type: {0} - Type de section non valide : {0} - - - - Section id missing - ID de section manquant - - - - Closing section tag not found - Balise de fermeture de section introuvable - - - - Invalid format in line {0}: {1} - Format non valide dans la ligne {0} : {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - '{0}' est manquant dans la section de projet lors de l'analyse de la ligne à partir de la position {1} - - - - Property set is missing '{0}' - '{0}' est manquant dans le jeu de propriétés - - - - File header is missing version - Version manquante pour l'en-tête de fichier - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.it.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.it.xlf deleted file mode 100644 index a19ec0313e93..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.it.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - La sezione Global è stata specificata più di una volta - - - - Global section not closed - La sezione Global non è stata chiusa - - - - Expected file header not found - L'intestazione del file prevista non è stata trovata - - - - Project section not closed - La sezione Project non è stata chiusa - - - - Invalid section type: {0} - Tipo di sezione non valido: {0} - - - - Section id missing - Manca l'ID sezione - - - - Closing section tag not found - Il tag di chiusura sessione non è stato trovato - - - - Invalid format in line {0}: {1} - Formato non valido alla riga {0}: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - Nella sezione del progetto manca '{0}' quando si analizza la riga a partire dalla posizione {1} - - - - Property set is missing '{0}' - Nel set di proprietà manca '{0}' - - - - File header is missing version - Nell'intestazione del file manca la versione - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.ja.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.ja.xlf deleted file mode 100644 index 0f7670d89f28..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.ja.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - グローバル セクションが 2 回以上指定されています - - - - Global section not closed - グローバル セクションが閉じられていません - - - - Expected file header not found - 予期されたファイル ヘッダーがありません - - - - Project section not closed - プロジェクト セクションが閉じられていません - - - - Invalid section type: {0} - 無効なセクションの種類: {0} - - - - Section id missing - セクション ID がありません - - - - Closing section tag not found - 終了セクション タグが見つかりません - - - - Invalid format in line {0}: {1} - 行 {0} の形式が無効です: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - 位置 {1} から始まる行の解析中にプロジェクト セクションが見つかりません '{0}' - - - - Property set is missing '{0}' - プロパティ セットが見つかりません '{0}' - - - - File header is missing version - ファイル ヘッダーにバージョンが見つかりません - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.ko.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.ko.xlf deleted file mode 100644 index 7d8766ad5dda..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.ko.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - 전역 섹션이 두 번 이상 지정됨 - - - - Global section not closed - 전역 섹션이 닫히지 않음 - - - - Expected file header not found - 필요한 파일 헤더가 없음 - - - - Project section not closed - 프로젝트 섹션이 닫히지 않음 - - - - Invalid section type: {0} - 잘못된 섹션 유형: {0} - - - - Section id missing - 섹션 ID가 누락됨 - - - - Closing section tag not found - 닫기 섹션 태그를 찾을 수 없음 - - - - Invalid format in line {0}: {1} - {0} 줄에 잘못된 형식: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - {1} 위치에서 시작하는 줄을 구문 분석할 때 프로젝트 섹션에 '{0}'이(가) 없습니다. - - - - Property set is missing '{0}' - 속성 설정에 '{0}'이(가) 없습니다. - - - - File header is missing version - 파일 헤더에 버전이 없습니다. - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.pl.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.pl.xlf deleted file mode 100644 index 957ee2041b72..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.pl.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - Sekcja globalna została określona więcej niż raz - - - - Global section not closed - Nie zamknięto sekcji globalnej - - - - Expected file header not found - Nie znaleziono oczekiwanego nagłówka pliku - - - - Project section not closed - Nie zamknięto sekcji projektu - - - - Invalid section type: {0} - Nieprawidłowy typ sekcji: {0} - - - - Section id missing - Brak identyfikatora sekcji - - - - Closing section tag not found - Nie odnaleziono tagu zamykającego sekcję - - - - Invalid format in line {0}: {1} - Nieprawidłowy format w wierszu {0}: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - W sekcji projektu brakuje elementu „{0}” podczas analizowania wiersza, począwszy od pozycji {1} - - - - Property set is missing '{0}' - W zestawie właściwości brakuje elementu „{0}” - - - - File header is missing version - Brak wersji nagłówka pliku - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.pt-BR.xlf deleted file mode 100644 index 877faf844fb7..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.pt-BR.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - Seção global especificada mais de uma vez - - - - Global section not closed - Seção global não fechada - - - - Expected file header not found - Cabeçalho do arquivo esperado não encontrado - - - - Project section not closed - Seção de projeto não fechada - - - - Invalid section type: {0} - Tipo de seção inválido: {0} - - - - Section id missing - ID de sessão ausente - - - - Closing section tag not found - Marca de fechamento de seção não encontrada - - - - Invalid format in line {0}: {1} - Formato inválido na linha {0}: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - A seção do projeto está sem o '{0}' ao analisar a linha na posição {1} - - - - Property set is missing '{0}' - O conjunto de propriedade está sem '{0}' - - - - File header is missing version - O cabeçalho do arquivo está sem a versão - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.ru.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.ru.xlf deleted file mode 100644 index 7caa01a43eef..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.ru.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - Глобальный раздел указан более одного раза. - - - - Global section not closed - Глобальный раздел не закрыт. - - - - Expected file header not found - Отсутствует требуемый заголовок файла - - - - Project section not closed - Раздел проекта не закрыт. - - - - Invalid section type: {0} - Недопустимый тип раздела: {0} - - - - Section id missing - Отсутствует идентификатор раздела. - - - - Closing section tag not found - Закрывающий тег раздела не найден. - - - - Invalid format in line {0}: {1} - Формат в строке {0} недопустим: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - В разделе проекта отсутствует "{0}" при анализе строки с начальной позицией {1} - - - - Property set is missing '{0}' - В наборе свойств отсутствует "{0}" - - - - File header is missing version - В заголовке файла отсутствует версия - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.tr.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.tr.xlf deleted file mode 100644 index a7c5cba6b88b..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.tr.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - Genel bölüm birden çok kez belirtilmiş - - - - Global section not closed - Genel bölüm kapatılmadı - - - - Expected file header not found - Beklenen dosya üst bilgisi bulunamadı - - - - Project section not closed - Proje bölümü kapatılmadı - - - - Invalid section type: {0} - Geçersiz bölüm türü: {0} - - - - Section id missing - Bölüm kimliği eksik - - - - Closing section tag not found - Kapatma bölümü etiketi bulunamadı - - - - Invalid format in line {0}: {1} - {0}. satırda geçersiz biçim: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - {1}. konumdan başlayan satır ayrıştırılırken proje bölümünde '{0}' eksik - - - - Property set is missing '{0}' - Özellik kümesinde '{0}' eksik - - - - File header is missing version - Dosya üst bilgisinde sürüm eksik - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.zh-Hans.xlf deleted file mode 100644 index b353d12475e4..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.zh-Hans.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - 多次指定了全局节 - - - - Global section not closed - 未关闭全局节 - - - - Expected file header not found - 未找到必需的文件头 - - - - Project section not closed - 未关闭项目节 - - - - Invalid section type: {0} - 无效的节类型: {0} - - - - Section id missing - 缺少节 ID - - - - Closing section tag not found - 未找到结束节标记 - - - - Invalid format in line {0}: {1} - 行 {0} 存在无效格式: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - 分析从位置 {1} 开始的行时,项目节缺少“{0}” - - - - Property set is missing '{0}' - 属性集缺少“{0}” - - - - File header is missing version - 文件头缺少版本 - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.zh-Hant.xlf deleted file mode 100644 index 7fef8a4f8621..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.zh-Hant.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - 全域區段指定了一次以上 - - - - Global section not closed - 全域區段未關閉 - - - - Expected file header not found - 找不到預期的檔案標頭 - - - - Project section not closed - 專案區段未關閉 - - - - Invalid section type: {0} - 區段類型無效: {0} - - - - Section id missing - 遺漏區段識別碼 - - - - Closing section tag not found - 找不到關閉區段標記 - - - - Invalid format in line {0}: {1} - 第 {0} 行的格式不正確: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - 從位置 {1} 開始剖析程式行時,專案區段缺少 '{0}' - - - - Property set is missing '{0}' - 屬性集缺少 '{0}' - - - - File header is missing version - 檔案標頭遺漏版本 - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/PathUtility.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/PathUtility.cs index 60069f1aa672..75e20189e680 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Utils/PathUtility.cs +++ b/src/Cli/Microsoft.DotNet.Cli.Utils/PathUtility.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Text.RegularExpressions; using Microsoft.DotNet.Cli.Utils; using NuGet.Configuration; @@ -388,5 +389,33 @@ public static void EnsureAllPathsExist( public static bool IsDirectory(this string path) => File.GetAttributes(path).HasFlag(FileAttributes.Directory); + + public static string FixFilePath(string path) + { + return string.IsNullOrEmpty(path) || Path.DirectorySeparatorChar == '\\' ? path : path.Replace('\\', '/'); + } + + public static string GetDirectorySeparatorChar() + { + return Regex.Escape(Path.DirectorySeparatorChar.ToString()); + } + + public static string? FindFileInParentDirectories(string startDirectory, string relativeFilePath) + { + var directory = new DirectoryInfo(startDirectory); + + while (directory != null) + { + var filePath = Path.Combine(directory.FullName, relativeFilePath); + if (File.Exists(filePath)) + { + return filePath; + } + + directory = directory.Parent; + } + + return null; + } } } diff --git a/src/Cli/Microsoft.DotNet.Configurer/CliFolderPathCalculator.cs b/src/Cli/Microsoft.DotNet.Configurer/CliFolderPathCalculator.cs index 3b24e843b147..705ee86a2ab3 100644 --- a/src/Cli/Microsoft.DotNet.Configurer/CliFolderPathCalculator.cs +++ b/src/Cli/Microsoft.DotNet.Configurer/CliFolderPathCalculator.cs @@ -42,8 +42,6 @@ public static string WindowsNonExpandedToolsShimPath public static string ToolsResolverCachePath => Path.Combine(DotnetUserProfileFolderPath, ToolsResolverCacheFolderName); - public static string PlatformHomeVariableName => CliFolderPathCalculatorCore.PlatformHomeVariableName; - public static string DotnetHomePath { get diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/Commands/CliPathInfo.cs b/src/Cli/Microsoft.TemplateEngine.Cli/Commands/CliPathInfo.cs index f5c4cea88861..668f7f59298c 100644 --- a/src/Cli/Microsoft.TemplateEngine.Cli/Commands/CliPathInfo.cs +++ b/src/Cli/Microsoft.TemplateEngine.Cli/Commands/CliPathInfo.cs @@ -24,7 +24,7 @@ public CliPathInfo( throw new ArgumentException($"{nameof(host.Version)} of {nameof(host)} cannot be null or whitespace.", nameof(host)); } - UserProfileDir = GetUserProfileDir(environment); + UserProfileDir = CliFolderPathCalculator.DotnetHomePath; GlobalSettingsDir = GetGlobalSettingsDir(settingsLocation); HostSettingsDir = Path.Combine(GlobalSettingsDir, host.HostIdentifier); HostVersionSettingsDir = Path.Combine(GlobalSettingsDir, host.HostIdentifier, host.Version); @@ -38,13 +38,6 @@ public CliPathInfo( public string HostVersionSettingsDir { get; } - private static string GetUserProfileDir(IEnvironment environment) => environment.GetEnvironmentVariable( - RuntimeInformation.IsOSPlatform(OSPlatform.Windows) - ? "USERPROFILE" - : "HOME") - ?? Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) - ?? throw new NotSupportedException("HOME or USERPROFILE environment variable is not defined, the environment is not supported"); - private static string GetGlobalSettingsDir(string? settingsLocation) { var definedSettingsLocation = string.IsNullOrWhiteSpace(settingsLocation) diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/TemplatePackageCoordinator.cs b/src/Cli/Microsoft.TemplateEngine.Cli/TemplatePackageCoordinator.cs index b4dda2fd7a46..07235e262599 100644 --- a/src/Cli/Microsoft.TemplateEngine.Cli/TemplatePackageCoordinator.cs +++ b/src/Cli/Microsoft.TemplateEngine.Cli/TemplatePackageCoordinator.cs @@ -208,9 +208,9 @@ internal async Task EnterInstallFlowAsync(InstallCommandArgs a foreach (string installArg in args.TemplatePackages) { - string[] splitByColons = installArg.Split(new[] { "::" }, StringSplitOptions.RemoveEmptyEntries); - string identifier = splitByColons[0]; - string? version = splitByColons.Length > 1 ? splitByColons[1] : null; + string[] split = installArg.Split(["::"], StringSplitOptions.RemoveEmptyEntries).SelectMany(arg => arg.Split('@', StringSplitOptions.RemoveEmptyEntries)).ToArray(); + string identifier = split[0]; + string? version = split.Length > 1 ? split[1] : null; foreach (string expandedIdentifier in InstallRequestPathResolution.ExpandMaskedPath(identifier, _engineEnvironmentSettings)) { installRequests.Add(new InstallRequest(expandedIdentifier, version, details: details, force: args.Force)); diff --git a/src/Cli/dotnet/CommandFactory/CommandResolution/ProjectToolsCommandResolver.cs b/src/Cli/dotnet/CommandFactory/CommandResolution/ProjectToolsCommandResolver.cs index d4b8733e8c30..16962233b2a1 100644 --- a/src/Cli/dotnet/CommandFactory/CommandResolution/ProjectToolsCommandResolver.cs +++ b/src/Cli/dotnet/CommandFactory/CommandResolution/ProjectToolsCommandResolver.cs @@ -337,7 +337,7 @@ internal void GenerateDepsJsonFile( LocalizableStrings.GeneratingDepsJson, depsPath)); - var tempDepsFile = Path.GetTempFileName(); + var tempDepsFile = Path.Combine(PathUtilities.CreateTempSubdirectory(), Path.GetRandomFileName()); var args = new List(); diff --git a/src/Cli/dotnet/CommonLocalizableStrings.resx b/src/Cli/dotnet/CommonLocalizableStrings.resx index 58c9371ccd01..9ef2b4a474f9 100644 --- a/src/Cli/dotnet/CommonLocalizableStrings.resx +++ b/src/Cli/dotnet/CommonLocalizableStrings.resx @@ -698,6 +698,25 @@ setx PATH "%PATH%;{0}" Specifying both the `-r|--runtime` and `-os` options is not supported. + + Sets the value of an environment variable. +Creates the variable if it does not exist, overrides if it does. +This will force the tests to be run in an isolated process. +This argument can be specified multiple times to provide multiple variables. + +Examples: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + + + NAME="VALUE" + + + Incorrectly formatted environment variables: {0} + Publish the .NET runtime with your application so the runtime doesn't need to be installed on the target machine. The default is 'false.' However, when targeting .NET 7 or lower, the default is 'true' if a runtime identifier is specified. @@ -715,6 +734,10 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is Response file '{0}' does not exist. + + Search for available workload versions or what comprises a workload version. Use 'dotnet workload search version --help' for more information. + {Locked="dotnet workload search version --help"} + The solution file '{0}' is missing EndProject tags or has invalid child-parent project folder mappings around project GUID: '{1}'. Manually repair the solution or try to open and save it in Visual Studio." diff --git a/src/Cli/dotnet/CommonOptions.cs b/src/Cli/dotnet/CommonOptions.cs index 95a86ec9984b..f544d89cc38e 100644 --- a/src/Cli/dotnet/CommonOptions.cs +++ b/src/Cli/dotnet/CommonOptions.cs @@ -3,6 +3,7 @@ using System.CommandLine; using System.CommandLine.Completions; +using System.CommandLine.Parsing; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Tools; using Microsoft.DotNet.Tools.Common; @@ -174,6 +175,52 @@ internal static string ArchOptionValue(ParseResult parseResult) => // Flip the argument so that if this option is specified we get selfcontained=false .SetForwardingFunction((arg, p) => ForwardSelfContainedOptions(!arg, p)); + public static readonly CliOption> EnvOption = new("--environment", "-e") + { + Description = CommonLocalizableStrings.CmdEnvironmentVariableDescription, + HelpName = CommonLocalizableStrings.CmdEnvironmentVariableExpression, + CustomParser = ParseEnvironmentVariables, + // Can't allow multiple arguments because the separator needs to be parsed as part of the environment variable value. + AllowMultipleArgumentsPerToken = false + }; + + private static IReadOnlyDictionary ParseEnvironmentVariables(ArgumentResult argumentResult) + { + var result = new Dictionary( + RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal); + + List? invalid = null; + + foreach (var token in argumentResult.Tokens) + { + var separator = token.Value.IndexOf('='); + var (name, value) = (separator >= 0) + ? (token.Value[0..separator], token.Value[(separator + 1)..]) + : (token.Value, ""); + + name = name.Trim(); + + if (name != "") + { + result[name] = value; + } + else + { + invalid ??= []; + invalid.Add(token); + } + } + + if (invalid != null) + { + argumentResult.AddError(string.Format( + CommonLocalizableStrings.IncorrectlyFormattedEnvironmentVariables, + string.Join(", ", invalid.Select(x => $"'{x.Value}'")))); + } + + return result; + } + public static readonly CliOption TestPlatformOption = new("--Platform"); public static readonly CliOption TestFrameworkOption = new("--Framework"); @@ -259,13 +306,6 @@ private static IEnumerable ForwardSelfContainedOptions(bool isSelfContai return selfContainedProperties; } - private static bool UserSpecifiedRidOption(ParseResult parseResult) => - (parseResult.GetResult(RuntimeOption) ?? - parseResult.GetResult(LongFormRuntimeOption) ?? - parseResult.GetResult(ArchitectureOption) ?? - parseResult.GetResult(LongFormArchitectureOption) ?? - parseResult.GetResult(OperatingSystemOption)) is not null; - internal static CliOption AddCompletions(this CliOption option, Func> completionSource) { option.CompletionSources.Add(completionSource); diff --git a/src/Cli/dotnet/NugetPackageDownloader/NuGetPackageDownloader.cs b/src/Cli/dotnet/NugetPackageDownloader/NuGetPackageDownloader.cs index 3b30a99345a4..201255fbdef9 100644 --- a/src/Cli/dotnet/NugetPackageDownloader/NuGetPackageDownloader.cs +++ b/src/Cli/dotnet/NugetPackageDownloader/NuGetPackageDownloader.cs @@ -552,7 +552,8 @@ await Task.WhenAll( IEnumerable<(PackageSource source, IPackageSearchMetadata package)> accumulativeSearchResults = foundPackagesBySource - .SelectMany(result => result.foundPackages.Select(package => (result.source, package))); + .SelectMany(result => result.foundPackages.Select(package => (result.source, package))) + .Distinct(); if (!accumulativeSearchResults.Any()) { @@ -570,7 +571,8 @@ await Task.WhenAll( if (stableVersions.Any()) { - return stableVersions.OrderByDescending(r => r.package.Identity.Version).Take(numberOfResults); + var results = stableVersions.OrderByDescending(r => r.package.Identity.Version); + return numberOfResults > 0 /* 0 indicates 'all' */ ? results.Take(numberOfResults) : results; } } diff --git a/src/Cli/dotnet/Parser.cs b/src/Cli/dotnet/Parser.cs index 04374a3e44ea..000f2c20a807 100644 --- a/src/Cli/dotnet/Parser.cs +++ b/src/Cli/dotnet/Parser.cs @@ -237,6 +237,8 @@ private static void SetHelpCustomizations(HelpBuilder builder) }; builder.CustomizeSymbol(option, secondColumnText: descriptionCallback); } + + builder.CustomizeSymbol(WorkloadSearchVersionsCommandParser.GetCommand(), secondColumnText: CommonLocalizableStrings.ShortWorkloadSearchVersionDescription); } public void additionalOption(HelpContext context) diff --git a/src/Cli/dotnet/ProjectInstanceExtensions.cs b/src/Cli/dotnet/ProjectInstanceExtensions.cs index 29337fa22c35..eea4778316d3 100644 --- a/src/Cli/dotnet/ProjectInstanceExtensions.cs +++ b/src/Cli/dotnet/ProjectInstanceExtensions.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.Build.Execution; -using Microsoft.DotNet.Cli.Sln.Internal; namespace Microsoft.DotNet.Tools.Common { @@ -22,7 +21,7 @@ public static string GetDefaultProjectTypeGuid(this ProjectInstance projectInsta string projectTypeGuid = projectInstance.GetPropertyValue("DefaultProjectTypeGuid"); if (string.IsNullOrEmpty(projectTypeGuid) && projectInstance.FullPath.EndsWith(".shproj", StringComparison.OrdinalIgnoreCase)) { - projectTypeGuid = ProjectTypeGuids.SharedProjectGuid; + projectTypeGuid = "{D954291E-2A0B-460D-934E-DC6B0785DB48}"; } return projectTypeGuid; } diff --git a/src/Cli/dotnet/Properties/launchSettings.json b/src/Cli/dotnet/Properties/launchSettings.json index 8d0ebf35dc6f..d3e2ca78d63b 100644 --- a/src/Cli/dotnet/Properties/launchSettings.json +++ b/src/Cli/dotnet/Properties/launchSettings.json @@ -1,7 +1,9 @@ { "profiles": { "dotnet": { - "commandName": "Project" + "commandName": "Project", + "commandLineArgs": "run -e MyCoolEnvironmentVariableKey=OverriddenEnvironmentVariableValue", + "workingDirectory": "C:\\sdk5\\artifacts\\tmp\\Debug\\EnvOptionLaun---86C8BD0D" } } -} \ No newline at end of file +} diff --git a/src/Cli/dotnet/ReleasePropertyProjectLocator.cs b/src/Cli/dotnet/ReleasePropertyProjectLocator.cs index 2bb50a56e63a..c03f3dfdadaf 100644 --- a/src/Cli/dotnet/ReleasePropertyProjectLocator.cs +++ b/src/Cli/dotnet/ReleasePropertyProjectLocator.cs @@ -4,11 +4,13 @@ using System.CommandLine; using System.Diagnostics; using Microsoft.Build.Execution; -using Microsoft.DotNet.Cli.Sln.Internal; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Tools; using Microsoft.DotNet.Tools.Common; using Microsoft.NET.Build.Tasks; +using Microsoft.VisualStudio.SolutionPersistence; +using Microsoft.VisualStudio.SolutionPersistence.Model; +using Microsoft.VisualStudio.SolutionPersistence.Serializer; namespace Microsoft.DotNet.Cli { @@ -128,7 +130,7 @@ public IEnumerable GetCustomDefaultConfigurationValueIfSpecified() } catch (GracefulException) // Fall back to looking for a solution if multiple project files are found, or there's no project in the directory. { - string? potentialSln = Directory.GetFiles(arg, "*.sln", SearchOption.TopDirectoryOnly).FirstOrDefault(); + string? potentialSln = SlnFileFactory.ListSolutionFilesInDirectory(arg, false).FirstOrDefault(); if (!string.IsNullOrEmpty(potentialSln)) { @@ -144,10 +146,15 @@ public IEnumerable GetCustomDefaultConfigurationValueIfSpecified() /// Throws exception if two+ projects disagree in PublishRelease, PackRelease, or whatever _propertyToCheck is, and have it defined. public ProjectInstance? GetArbitraryProjectFromSolution(string slnPath, Dictionary globalProps) { - SlnFile sln; + string slnFullPath = Path.GetFullPath(slnPath); + if (!Path.Exists(slnFullPath)) + { + return null; + } + SolutionModel sln; try { - sln = SlnFileFactory.CreateFromFileOrDirectory(slnPath); + sln = SlnFileFactory.CreateFromFileOrDirectory(slnFullPath, false, false); } catch (GracefulException) { @@ -162,13 +169,13 @@ public IEnumerable GetCustomDefaultConfigurationValueIfSpecified() if (string.Equals(Environment.GetEnvironmentVariable(EnvironmentVariableNames.DOTNET_CLI_LAZY_PUBLISH_AND_PACK_RELEASE_FOR_SOLUTIONS), "true", StringComparison.OrdinalIgnoreCase)) { // Evaluate only one project for speed if this environment variable is used. Will break more customers if enabled (adding 8.0 project to SLN with other project TFMs with no Publish or PackRelease.) - return GetSingleProjectFromSolution(sln, globalProps); + return GetSingleProjectFromSolution(sln, slnFullPath, globalProps); } - Parallel.ForEach(sln.Projects.AsEnumerable(), (project, state) => + Parallel.ForEach(sln.SolutionProjects.AsEnumerable(), (project, state) => { #pragma warning disable CS8604 // Possible null reference argument. - string projectFullPath = Path.Combine(Path.GetDirectoryName(sln.FullPath), project.FilePath); + string projectFullPath = Path.Combine(Path.GetDirectoryName(slnFullPath), project.FilePath); #pragma warning restore CS8604 // Possible null reference argument. if (IsUnanalyzableProjectInSolution(project, projectFullPath)) return; @@ -207,12 +214,12 @@ public IEnumerable GetCustomDefaultConfigurationValueIfSpecified() /// The solution to get an arbitrary project from. /// The global properties to load into the project. /// null if no project exists in the solution that can be evaluated properly. Else, the first project in the solution that can be. - private ProjectInstance? GetSingleProjectFromSolution(SlnFile sln, Dictionary globalProps) + private ProjectInstance? GetSingleProjectFromSolution(SolutionModel sln, string slnPath, Dictionary globalProps) { - foreach (var project in sln.Projects.AsEnumerable()) + foreach (var project in sln.SolutionProjects.AsEnumerable()) { #pragma warning disable CS8604 // Possible null reference argument. - string projectFullPath = Path.Combine(Path.GetDirectoryName(sln.FullPath), project.FilePath); + string projectFullPath = Path.Combine(Path.GetDirectoryName(slnPath), project.FilePath); #pragma warning restore CS8604 // Possible null reference argument. if (IsUnanalyzableProjectInSolution(project, projectFullPath)) continue; @@ -233,9 +240,9 @@ public IEnumerable GetCustomDefaultConfigurationValueIfSpecified() /// The project under a solution to evaluate. /// The full hard-coded path of the project. /// True if the project is not supported by ProjectInstance class or appears to be invalid. - private bool IsUnanalyzableProjectInSolution(SlnProject project, string projectFullPath) + private bool IsUnanalyzableProjectInSolution(SolutionProjectModel project, string projectFullPath) { - return project.TypeGuid == solutionFolderGuid || project.TypeGuid == sharedProjectGuid || !IsValidProjectFilePath(projectFullPath); + return project.TypeId.ToString() == solutionFolderGuid || project.TypeId.ToString() == sharedProjectGuid || !IsValidProjectFilePath(projectFullPath); } /// Creates a ProjectInstance if the project is valid, elsewise, fails. @@ -261,7 +268,7 @@ private bool IsValidProjectFilePath(string path) /// Returns true if the path exists and is a sln file type. private bool IsValidSlnFilePath(string path) { - return File.Exists(path) && Path.GetExtension(path).EndsWith("sln"); + return File.Exists(path) && (Path.GetExtension(path).Equals(".sln")|| Path.GetExtension(path).Equals(".slnx")); } /// A case-insensitive dictionary of any properties passed from the user and their values. diff --git a/src/Cli/dotnet/SlnFileExtensions.cs b/src/Cli/dotnet/SlnFileExtensions.cs deleted file mode 100644 index 22b5cc48c5a8..000000000000 --- a/src/Cli/dotnet/SlnFileExtensions.cs +++ /dev/null @@ -1,540 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.Build.Construction; -using Microsoft.Build.Exceptions; -using Microsoft.Build.Execution; -using Microsoft.DotNet.Cli.Sln.Internal; -using Microsoft.DotNet.Cli.Utils; - -namespace Microsoft.DotNet.Tools.Common -{ - internal static class SlnFileExtensions - { - public static void AddProject(this SlnFile slnFile, string fullProjectPath, IList solutionFolders) - { - if (string.IsNullOrEmpty(fullProjectPath)) - { - throw new ArgumentException(); - } - - var relativeProjectPath = Path.GetRelativePath( - PathUtility.EnsureTrailingSlash(slnFile.BaseDirectory), - fullProjectPath); - - if (slnFile.Projects.Any((p) => - string.Equals(p.FilePath, relativeProjectPath, StringComparison.OrdinalIgnoreCase))) - { - Reporter.Output.WriteLine(string.Format( - CommonLocalizableStrings.SolutionAlreadyContainsProject, - slnFile.FullPath, - relativeProjectPath)); - } - else - { - ProjectRootElement rootElement = null; - ProjectInstance projectInstance = null; - try - { - rootElement = ProjectRootElement.Open(fullProjectPath); - projectInstance = new ProjectInstance(rootElement); - } - catch (InvalidProjectFileException e) - { - Reporter.Error.WriteLine(string.Format( - CommonLocalizableStrings.InvalidProjectWithExceptionMessage, - fullProjectPath, - e.Message)); - return; - } - - var slnProject = new SlnProject - { - Id = projectInstance.GetProjectId(), - TypeGuid = rootElement.GetProjectTypeGuid() ?? projectInstance.GetDefaultProjectTypeGuid(), - Name = Path.GetFileNameWithoutExtension(relativeProjectPath), - FilePath = relativeProjectPath - }; - - if (string.IsNullOrEmpty(slnProject.TypeGuid)) - { - Reporter.Error.WriteLine( - string.Format( - CommonLocalizableStrings.UnsupportedProjectType, - projectInstance.FullPath)); - return; - } - - // NOTE: The order you create the sections determines the order they are written to the sln - // file. In the case of an empty sln file, in order to make sure the solution configurations - // section comes first we need to add it first. This doesn't affect correctness but does - // stop VS from re-ordering things later on. Since we are keeping the SlnFile class low-level - // it shouldn't care about the VS implementation details. That's why we handle this here. - if (AreBuildConfigurationsApplicable(slnProject.TypeGuid)) - { - slnFile.AddDefaultBuildConfigurations(); - - slnFile.MapSolutionConfigurationsToProject( - projectInstance, - slnFile.ProjectConfigurationsSection.GetOrCreatePropertySet(slnProject.Id)); - } - - SetupSolutionFolders(slnFile, solutionFolders, relativeProjectPath, slnProject); - - slnFile.Projects.Add(slnProject); - - Reporter.Output.WriteLine( - string.Format(CommonLocalizableStrings.ProjectAddedToTheSolution, relativeProjectPath)); - } - } - - private static bool AreBuildConfigurationsApplicable(string projectTypeGuid) - { - return !projectTypeGuid.Equals(ProjectTypeGuids.SharedProjectGuid, StringComparison.OrdinalIgnoreCase); - } - - private static void SetupSolutionFolders(SlnFile slnFile, IList solutionFolders, string relativeProjectPath, SlnProject slnProject) - { - if (solutionFolders != null) - { - if (solutionFolders.Any()) - { - // Before adding a solution folder, check if the name conflicts with any existing projects in the solution - var duplicateProjects = slnFile.Projects.Where(p => solutionFolders.Contains(p.Name) - && p.TypeGuid != ProjectTypeGuids.SolutionFolderGuid).ToList(); - foreach (SlnProject duplicateProject in duplicateProjects) - { - slnFile.AddSolutionFolders(duplicateProject, new List() { Path.GetDirectoryName(duplicateProject.FilePath) }); - } - } - else - { - // If a project and solution folder have the same name, add it's own folder as a solution folder - // eg. foo\extensions.csproj and extensions\library\library.csproj would have a project and solution folder with conflicting names - var duplicateProject = slnFile.Projects.Where(p => string.Equals(p.Name, slnProject.Name, StringComparison.OrdinalIgnoreCase) - && p.TypeGuid == ProjectTypeGuids.SolutionFolderGuid).FirstOrDefault(); - if (duplicateProject != null) - { - // Try making a new folder for the project to put it under so we can still add it despite there being one with the same name already in the parent folder - slnFile.AddSolutionFolders(slnProject, new List() { Path.GetDirectoryName(relativeProjectPath) }); - } - } - // Even if we added a solution folder above for a duplicate, we still need to add the expected folder for the current project - slnFile.AddSolutionFolders(slnProject, solutionFolders); - } - } - - private static void AddDefaultBuildConfigurations(this SlnFile slnFile) - { - var configurationsSection = slnFile.SolutionConfigurationsSection; - - if (!configurationsSection.IsEmpty) - { - return; - } - - var defaultConfigurations = new List() - { - "Debug|Any CPU", - "Debug|x64", - "Debug|x86", - "Release|Any CPU", - "Release|x64", - "Release|x86", - }; - - foreach (var config in defaultConfigurations) - { - configurationsSection[config] = config; - } - } - - private static void MapSolutionConfigurationsToProject( - this SlnFile slnFile, - ProjectInstance projectInstance, - SlnPropertySet solutionProjectConfigs) - { - var (projectConfigurations, defaultProjectConfiguration) = GetKeysDictionary(projectInstance.GetConfigurations()); - var (projectPlatforms, defaultProjectPlatform) = GetKeysDictionary(projectInstance.GetPlatforms()); - - foreach (var solutionConfigKey in slnFile.SolutionConfigurationsSection.Keys) - { - var projectConfigKey = MapSolutionConfigKeyToProjectConfigKey( - solutionConfigKey, - projectConfigurations, - defaultProjectConfiguration, - projectPlatforms, - defaultProjectPlatform); - if (projectConfigKey == null) - { - continue; - } - - var activeConfigKey = $"{solutionConfigKey}.ActiveCfg"; - if (!solutionProjectConfigs.ContainsKey(activeConfigKey)) - { - solutionProjectConfigs[activeConfigKey] = projectConfigKey; - } - - var buildKey = $"{solutionConfigKey}.Build.0"; - if (!solutionProjectConfigs.ContainsKey(buildKey)) - { - solutionProjectConfigs[buildKey] = projectConfigKey; - } - } - } - - private static (Dictionary Keys, string DefaultKey) GetKeysDictionary(IEnumerable keys) - { - // A dictionary mapping key -> key is used instead of a HashSet so the original case of the key can be retrieved from the set - var dictionary = new Dictionary(StringComparer.CurrentCultureIgnoreCase); - - foreach (var key in keys) - { - dictionary[key] = key; - } - - return (dictionary, keys.FirstOrDefault()); - } - - private static string GetMatchingProjectKey(IDictionary projectKeys, string solutionKey) - { - string projectKey; - if (projectKeys.TryGetValue(solutionKey, out projectKey)) - { - return projectKey; - } - - var keyWithoutWhitespace = string.Concat(solutionKey.Where(c => !char.IsWhiteSpace(c))); - if (projectKeys.TryGetValue(keyWithoutWhitespace, out projectKey)) - { - return projectKey; - } - - return null; - } - - private static string MapSolutionConfigKeyToProjectConfigKey( - string solutionConfigKey, - Dictionary projectConfigurations, - string defaultProjectConfiguration, - Dictionary projectPlatforms, - string defaultProjectPlatform) - { - var pair = solutionConfigKey.Split(new char[] { '|' }, 2); - if (pair.Length != 2) - { - return null; - } - - var projectConfiguration = GetMatchingProjectKey(projectConfigurations, pair[0]) ?? defaultProjectConfiguration; - if (projectConfiguration == null) - { - return null; - } - - var projectPlatform = GetMatchingProjectKey(projectPlatforms, pair[1]) ?? defaultProjectPlatform; - if (projectPlatform == null) - { - return null; - } - - // VS stores "Any CPU" platform in the solution regardless of how it is named at the project level - return $"{projectConfiguration}|{(projectPlatform == "AnyCPU" ? "Any CPU" : projectPlatform)}"; - } - - private static void AddSolutionFolders(this SlnFile slnFile, SlnProject slnProject, IList solutionFolders) - { - if (solutionFolders.Any()) - { - var nestedProjectsSection = slnFile.Sections.GetOrCreateSection( - "NestedProjects", - SlnSectionType.PreProcess); - - var pathToGuidMap = slnFile.GetSolutionFolderPaths(nestedProjectsSection.Properties); - - if (slnFile.HasSolutionFolder(nestedProjectsSection.Properties, slnProject)) - { - return; - } - - string parentDirGuid = null; - var solutionFolderHierarchy = string.Empty; - foreach (var dir in solutionFolders) - { - solutionFolderHierarchy = Path.Combine(solutionFolderHierarchy, dir); - if (pathToGuidMap.ContainsKey(solutionFolderHierarchy)) - { - parentDirGuid = pathToGuidMap[solutionFolderHierarchy]; - } - else - { - - if (HasDuplicateNameForSameValueOfNestedProjects(nestedProjectsSection, dir, parentDirGuid, slnFile.Projects)) - { - throw new GracefulException(CommonLocalizableStrings.SolutionFolderAlreadyContainsProject, slnFile.FullPath, slnProject.Name, slnFile.Projects.FirstOrDefault(p => p.Id == parentDirGuid).Name); - } - - var solutionFolder = new SlnProject - { - Id = Guid.NewGuid().ToString("B").ToUpper(), - TypeGuid = ProjectTypeGuids.SolutionFolderGuid, - Name = dir, - FilePath = dir - }; - - slnFile.Projects.Add(solutionFolder); - - if (parentDirGuid != null) - { - nestedProjectsSection.Properties[solutionFolder.Id] = parentDirGuid; - } - parentDirGuid = solutionFolder.Id; - } - } - if (HasDuplicateNameForSameValueOfNestedProjects(nestedProjectsSection, slnProject.Name, parentDirGuid, slnFile.Projects)) - { - throw new GracefulException(CommonLocalizableStrings.SolutionFolderAlreadyContainsProject, slnFile.FullPath, slnProject.Name, slnFile.Projects.FirstOrDefault(p => p.Id == parentDirGuid).Name); - } - nestedProjectsSection.Properties[slnProject.Id] = parentDirGuid; - } - } - - private static bool HasDuplicateNameForSameValueOfNestedProjects(SlnSection nestedProjectsSection, string name, string value, IList projects) - { - foreach (var property in nestedProjectsSection.Properties) - { - if (property.Value == value) - { - var existingProject = projects.FirstOrDefault(p => p.Id == property.Key); - - if (existingProject != null && existingProject.Name == name) - { - return true; - } - } - } - return false; - } - - private static IDictionary GetSolutionFolderPaths( - this SlnFile slnFile, - SlnPropertySet nestedProjects) - { - var solutionFolderPaths = new Dictionary(StringComparer.OrdinalIgnoreCase); - - var solutionFolderProjects = slnFile.Projects.GetProjectsByType(ProjectTypeGuids.SolutionFolderGuid); - foreach (var slnProject in solutionFolderProjects) - { - var path = slnProject.FilePath; - var id = slnProject.Id; - while (nestedProjects.ContainsKey(id)) - { - id = nestedProjects[id]; - var parentSlnProject = solutionFolderProjects.Where(p => p.Id == id).SingleOrDefault(); - if (parentSlnProject == null) // see: https://github.com/dotnet/sdk/pull/28811 - throw new GracefulException(CommonLocalizableStrings.CorruptSolutionProjectFolderStructure, slnFile.FullPath, id); - path = Path.Combine(parentSlnProject.FilePath, path); - } - - solutionFolderPaths[path] = slnProject.Id; - } - - return solutionFolderPaths; - } - - private static bool HasSolutionFolder( - this SlnFile slnFile, - SlnPropertySet properties, - SlnProject slnProject) - { - return properties.ContainsKey(slnProject.Id); - } - - public static bool RemoveProject(this SlnFile slnFile, string projectPath) - { - if (string.IsNullOrEmpty(projectPath)) - { - throw new ArgumentException(); - } - - var projectPathNormalized = PathUtility.GetPathWithDirectorySeparator(projectPath); - - var projectsToRemove = slnFile.Projects.Where((p) => - string.Equals(p.FilePath, projectPathNormalized, StringComparison.OrdinalIgnoreCase)).ToList(); - - bool projectRemoved = false; - if (projectsToRemove.Count == 0) - { - Reporter.Output.WriteLine(string.Format( - CommonLocalizableStrings.ProjectNotFoundInTheSolution, - projectPath)); - } - else - { - foreach (var slnProject in projectsToRemove) - { - var buildConfigsToRemove = slnFile.ProjectConfigurationsSection.GetPropertySet(slnProject.Id); - if (buildConfigsToRemove != null) - { - slnFile.ProjectConfigurationsSection.Remove(buildConfigsToRemove); - } - - var nestedProjectsSection = slnFile.Sections.GetSection( - "NestedProjects", - SlnSectionType.PreProcess); - if (nestedProjectsSection != null && nestedProjectsSection.Properties.ContainsKey(slnProject.Id)) - { - nestedProjectsSection.Properties.Remove(slnProject.Id); - } - - slnFile.Projects.Remove(slnProject); - Reporter.Output.WriteLine( - string.Format(CommonLocalizableStrings.ProjectRemovedFromTheSolution, slnProject.FilePath)); - } - - foreach (var project in slnFile.Projects) - { - var dependencies = project.Dependencies; - if (dependencies == null) - { - continue; - } - - dependencies.SkipIfEmpty = true; - - foreach (var removed in projectsToRemove) - { - dependencies.Properties.Remove(removed.Id); - } - } - - projectRemoved = true; - } - - return projectRemoved; - } - - public static void RemoveEmptyConfigurationSections(this SlnFile slnFile) - { - if (slnFile.Projects.Count == 0) - { - var solutionConfigs = slnFile.Sections.GetSection("SolutionConfigurationPlatforms"); - if (solutionConfigs != null) - { - slnFile.Sections.Remove(solutionConfigs); - } - - var projectConfigs = slnFile.Sections.GetSection("ProjectConfigurationPlatforms"); - if (projectConfigs != null) - { - slnFile.Sections.Remove(projectConfigs); - } - } - } - - public static void RemoveEmptySolutionFolders(this SlnFile slnFile) - { - var solutionFolderProjects = slnFile.Projects - .GetProjectsByType(ProjectTypeGuids.SolutionFolderGuid) - .ToList(); - - if (solutionFolderProjects.Any()) - { - var nestedProjectsSection = slnFile.Sections.GetSection( - "NestedProjects", - SlnSectionType.PreProcess); - - if (nestedProjectsSection == null) - { - foreach (var solutionFolderProject in solutionFolderProjects) - { - if (solutionFolderProject.Sections.Count() == 0) - { - slnFile.Projects.Remove(solutionFolderProject); - } - } - } - else - { - var solutionFoldersInUse = slnFile.GetSolutionFoldersThatContainProjectsInItsHierarchy( - nestedProjectsSection.Properties); - - solutionFoldersInUse.UnionWith(slnFile.GetSolutionFoldersThatContainSolutionItemsInItsHierarchy( - nestedProjectsSection.Properties)); - - foreach (var solutionFolderProject in solutionFolderProjects) - { - if (!solutionFoldersInUse.Contains(solutionFolderProject.Id)) - { - nestedProjectsSection.Properties.Remove(solutionFolderProject.Id); - if (solutionFolderProject.Sections.Count() == 0) - { - slnFile.Projects.Remove(solutionFolderProject); - } - } - } - - if (nestedProjectsSection.IsEmpty) - { - slnFile.Sections.Remove(nestedProjectsSection); - } - } - } - } - - private static HashSet GetSolutionFoldersThatContainProjectsInItsHierarchy( - this SlnFile slnFile, - SlnPropertySet nestedProjects) - { - var solutionFoldersInUse = new HashSet(); - - IEnumerable nonSolutionFolderProjects; - nonSolutionFolderProjects = slnFile.Projects.GetProjectsNotOfType( - ProjectTypeGuids.SolutionFolderGuid); - - foreach (var nonSolutionFolderProject in nonSolutionFolderProjects) - { - var id = nonSolutionFolderProject.Id; - while (nestedProjects.ContainsKey(id)) - { - id = nestedProjects[id]; - solutionFoldersInUse.Add(id); - } - } - - return solutionFoldersInUse; - } - - private static HashSet GetSolutionFoldersThatContainSolutionItemsInItsHierarchy( - this SlnFile slnFile, - SlnPropertySet nestedProjects) - { - var solutionFoldersInUse = new HashSet(); - - var solutionItemsFolderProjects = slnFile.Projects - .GetProjectsByType(ProjectTypeGuids.SolutionFolderGuid) - .Where(ContainsSolutionItems); - - foreach (var solutionItemsFolderProject in solutionItemsFolderProjects) - { - var id = solutionItemsFolderProject.Id; - solutionFoldersInUse.Add(id); - - while (nestedProjects.ContainsKey(id)) - { - id = nestedProjects[id]; - solutionFoldersInUse.Add(id); - } - } - - return solutionFoldersInUse; - } - - private static bool ContainsSolutionItems(SlnProject project) - { - return project.Sections - .GetSection("SolutionItems", SlnSectionType.PreProcess) != null; - } - } -} diff --git a/src/Cli/dotnet/SlnFileFactory.cs b/src/Cli/dotnet/SlnFileFactory.cs index 49a33de4c782..c93e30b3b0e8 100644 --- a/src/Cli/dotnet/SlnFileFactory.cs +++ b/src/Cli/dotnet/SlnFileFactory.cs @@ -1,86 +1,148 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.DotNet.Cli.Sln.Internal; +using System.Text.Json; +using System.Text.Json.Nodes; using Microsoft.DotNet.Cli.Utils; +using Microsoft.VisualStudio.SolutionPersistence; +using Microsoft.VisualStudio.SolutionPersistence.Model; +using Microsoft.VisualStudio.SolutionPersistence.Serializer; namespace Microsoft.DotNet.Tools.Common { public static class SlnFileFactory { - public static SlnFile CreateFromFileOrDirectory(string fileOrDirectory) + public static string GetSolutionFileFullPath(string slnFileOrDirectory, bool includeSolutionFilterFiles = false, bool includeSolutionXmlFiles = true) { - if (File.Exists(fileOrDirectory)) + // Throw error if slnFileOrDirectory is an invalid path + if (string.IsNullOrWhiteSpace(slnFileOrDirectory) || slnFileOrDirectory.IndexOfAny(Path.GetInvalidPathChars()) != -1) { - return FromFile(fileOrDirectory); + throw new GracefulException(CommonLocalizableStrings.CouldNotFindSolutionOrDirectory); } - else + if (File.Exists(slnFileOrDirectory)) { - return FromDirectory(fileOrDirectory); + return Path.GetFullPath(slnFileOrDirectory); } + if (Directory.Exists(slnFileOrDirectory)) + { + string[] files = ListSolutionFilesInDirectory(slnFileOrDirectory, includeSolutionFilterFiles, includeSolutionXmlFiles); + if (files.Length == 0) + { + throw new GracefulException( + CommonLocalizableStrings.CouldNotFindSolutionIn, + slnFileOrDirectory); + } + if (files.Length > 1) + { + throw new GracefulException( + CommonLocalizableStrings.MoreThanOneSolutionInDirectory, + slnFileOrDirectory); + } + return Path.GetFullPath(files.Single()); + } + throw new GracefulException( + CommonLocalizableStrings.CouldNotFindSolutionOrDirectory, + slnFileOrDirectory); } - private static SlnFile FromFile(string solutionPath) + + public static string[] ListSolutionFilesInDirectory(string directory, bool includeSolutionFilterFiles = false, bool includeSolutionXmlFiles = true) { - SlnFile slnFile = null; - try - { - slnFile = SlnFile.Read(solutionPath); - } - catch (InvalidSolutionFormatException e) + return [ + ..Directory.GetFiles(directory, "*.sln", SearchOption.TopDirectoryOnly), + ..(includeSolutionXmlFiles ? Directory.GetFiles(directory, "*.slnx", SearchOption.TopDirectoryOnly) : []), + ..(includeSolutionFilterFiles ? Directory.GetFiles(directory, "*.slnf", SearchOption.TopDirectoryOnly) : []) + ]; + } + + public static SolutionModel CreateFromFileOrDirectory(string fileOrDirectory, bool includeSolutionFilterFiles = false, bool includeSolutionXmlFiles = true) + { + string solutionPath = GetSolutionFileFullPath(fileOrDirectory, includeSolutionFilterFiles, includeSolutionXmlFiles); + + if (solutionPath.HasExtension(".slnf")) { - throw new GracefulException( - CommonLocalizableStrings.InvalidSolutionFormatString, - solutionPath, - e.Message); + return CreateFromFilteredSolutionFile(solutionPath); } - return slnFile; + ISolutionSerializer serializer = SolutionSerializers.GetSerializerByMoniker(solutionPath) ?? throw new GracefulException( + CommonLocalizableStrings.CouldNotFindSolutionOrDirectory, + solutionPath); + + return serializer.OpenAsync(solutionPath, CancellationToken.None).Result; } - private static SlnFile FromDirectory(string solutionDirectory) + public static SolutionModel CreateFromFilteredSolutionFile(string filteredSolutionPath) { - DirectoryInfo dir; + JsonDocument jsonDocument; + JsonElement jsonElement; + JsonElement filteredSolutionJsonElement; + string originalSolutionPath; + string originalSolutionPathAbsolute; + string[] filteredSolutionProjectPaths; + try { - dir = new DirectoryInfo(solutionDirectory); - if (!dir.Exists) + jsonDocument = JsonDocument.Parse(File.ReadAllText(filteredSolutionPath)); + jsonElement = jsonDocument.RootElement; + filteredSolutionJsonElement = jsonElement.GetProperty("solution"); + originalSolutionPath = filteredSolutionJsonElement.GetProperty("path").GetString(); + originalSolutionPathAbsolute = Path.GetFullPath(originalSolutionPath, Path.GetDirectoryName(filteredSolutionPath)); + if (!File.Exists(originalSolutionPathAbsolute)) { - throw new GracefulException( - CommonLocalizableStrings.CouldNotFindSolutionOrDirectory, - solutionDirectory); + throw new Exception(); } + filteredSolutionProjectPaths = filteredSolutionJsonElement.GetProperty("projects") + .EnumerateArray() + .Select(project => project.GetString()) + .ToArray(); } - catch (ArgumentException) + catch (Exception ex) { throw new GracefulException( - CommonLocalizableStrings.CouldNotFindSolutionOrDirectory, - solutionDirectory); + CommonLocalizableStrings.InvalidSolutionFormatString, + filteredSolutionPath, ex.Message); } - FileInfo[] files = dir.GetFiles("*.sln"); - if (files.Length == 0) + SolutionModel filteredSolution = new SolutionModel(); + SolutionModel originalSolution = CreateFromFileOrDirectory(originalSolutionPathAbsolute); + + foreach (var platform in originalSolution.Platforms) { - throw new GracefulException( - CommonLocalizableStrings.CouldNotFindSolutionIn, - solutionDirectory); + filteredSolution.AddPlatform(platform); + } + foreach (var buildType in originalSolution.BuildTypes) + { + filteredSolution.AddBuildType(buildType); } - if (files.Length > 1) + foreach (string path in filteredSolutionProjectPaths) { - throw new GracefulException( - CommonLocalizableStrings.MoreThanOneSolutionInDirectory, - solutionDirectory); + // Normalize path to use correct directory separator + string normalizedPath = path.Replace('\\', Path.DirectorySeparatorChar); + + SolutionProjectModel project = originalSolution.FindProject(normalizedPath) ?? throw new GracefulException( + CommonLocalizableStrings.ProjectNotFoundInTheSolution, + normalizedPath, + originalSolutionPath); + filteredSolution.AddProject(project.FilePath, project.Type, project.Parent is null ? null : filteredSolution.AddFolder(project.Parent.Path)); } - FileInfo solutionFile = files.Single(); - if (!solutionFile.Exists) + return filteredSolution; + } + + public static string GetSolutionPathFromFilteredSolutionFile(string filteredSolutionPath) + { + try + { + JsonNode? jsonNode = JsonNode.Parse(File.ReadAllText(filteredSolutionPath)); + string? originalSolutionPath = jsonNode?["solution"]?["path"]?.GetValue(); + return originalSolutionPath!; + } + catch (Exception ex) { throw new GracefulException( - CommonLocalizableStrings.CouldNotFindSolutionIn, - solutionDirectory); + CommonLocalizableStrings.InvalidSolutionFormatString, + filteredSolutionPath, ex.Message); } - - return FromFile(solutionFile.FullName); } } } diff --git a/src/Cli/dotnet/SlnProjectCollectionExtensions.cs b/src/Cli/dotnet/SlnProjectCollectionExtensions.cs deleted file mode 100644 index f0d70ae4e640..000000000000 --- a/src/Cli/dotnet/SlnProjectCollectionExtensions.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.DotNet.Cli.Sln.Internal; - -namespace Microsoft.DotNet.Tools.Common -{ - internal static class SlnProjectCollectionExtensions - { - public static IEnumerable GetProjectsByType( - this SlnProjectCollection projects, - string typeGuid) - { - return projects.Where(p => p.TypeGuid == typeGuid); - } - - public static IEnumerable GetProjectsNotOfType( - this SlnProjectCollection projects, - string typeGuid) - { - return projects.Where(p => p.TypeGuid != typeGuid); - } - } -} diff --git a/src/Cli/dotnet/SlnProjectExtensions.cs b/src/Cli/dotnet/SlnProjectExtensions.cs deleted file mode 100644 index 405c3b43cb88..000000000000 --- a/src/Cli/dotnet/SlnProjectExtensions.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.DotNet.Cli.Sln.Internal; - -namespace Microsoft.DotNet.Tools.Common -{ - internal static class SlnProjectExtensions - { - public static string GetFullSolutionFolderPath(this SlnProject slnProject) - { - var slnFile = slnProject.ParentFile; - var nestedProjects = slnFile.Sections - .GetOrCreateSection("NestedProjects", SlnSectionType.PreProcess) - .Properties; - var solutionFolders = slnFile.Projects - .GetProjectsByType(ProjectTypeGuids.SolutionFolderGuid) - .ToArray(); - - string path = slnProject.Name; - string id = slnProject.Id; - - // If the nested projects contains this project's id then it has a parent - // Traverse from the project to each parent prepending the solution folder to the path - while (nestedProjects.ContainsKey(id)) - { - id = nestedProjects[id]; - - string solutionFolderPath = solutionFolders.Single(p => p.Id == id).FilePath; - path = Path.Combine(solutionFolderPath, path); - } - - return path; - } - } -} diff --git a/src/Cli/dotnet/SudoEnvironmentDirectoryOverride.cs b/src/Cli/dotnet/SudoEnvironmentDirectoryOverride.cs index 66c0f405f8e9..e04f071b6693 100644 --- a/src/Cli/dotnet/SudoEnvironmentDirectoryOverride.cs +++ b/src/Cli/dotnet/SudoEnvironmentDirectoryOverride.cs @@ -3,6 +3,7 @@ using System.CommandLine; using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Configurer; using NuGet.Common; using NuGet.Configuration; @@ -32,8 +33,8 @@ public static void OverrideEnvironmentVariableToTmp(ParseResult parseResult) if (!OperatingSystem.IsWindows() && IsRunningUnderSudo() && IsRunningWorkloadCommand(parseResult)) { string sudoHome = PathUtilities.CreateTempSubdirectory(); - var homeBeforeOverride = Path.Combine(Environment.GetEnvironmentVariable("HOME")); - Environment.SetEnvironmentVariable("HOME", sudoHome); + var homeBeforeOverride = Path.Combine(Environment.GetEnvironmentVariable(CliFolderPathCalculator.DotnetHomeVariableName)); + Environment.SetEnvironmentVariable(CliFolderPathCalculator.DotnetHomeVariableName, sudoHome); CopyUserNuGetConfigToOverriddenHome(homeBeforeOverride); } diff --git a/src/Cli/dotnet/commands/InstallingWorkloadCommand.cs b/src/Cli/dotnet/commands/InstallingWorkloadCommand.cs index 8f8f2295333b..3da0e9887571 100644 --- a/src/Cli/dotnet/commands/InstallingWorkloadCommand.cs +++ b/src/Cli/dotnet/commands/InstallingWorkloadCommand.cs @@ -2,12 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.CommandLine; -using System.IO; -using System.Linq; -using System.Net.Http.Json; -using System.Runtime.CompilerServices; -using System.Text.Json; -using System.Text.Json.Nodes; using Microsoft.Deployment.DotNet.Releases; using Microsoft.DotNet.Cli; using Microsoft.DotNet.Cli.Commands.DotNetWorkloads; @@ -16,6 +10,7 @@ using Microsoft.DotNet.ToolPackage; using Microsoft.DotNet.Workloads.Workload.History; using Microsoft.DotNet.Workloads.Workload.Install; +using Microsoft.DotNet.Workloads.Workload.Search; using Microsoft.DotNet.Workloads.Workload.Update; using Microsoft.Extensions.EnvironmentAbstractions; using Microsoft.NET.Sdk.WorkloadManifestReader; @@ -41,7 +36,7 @@ internal abstract class InstallingWorkloadCommand : WorkloadCommandBase protected readonly string _fromRollbackDefinition; protected int _fromHistorySpecified; protected bool _historyManifestOnlyOption; - protected string _workloadSetVersionFromCommandLine; + protected IEnumerable _workloadSetVersionFromCommandLine; protected string _globalJsonPath; protected string _workloadSetVersionFromGlobalJson; protected readonly PackageSourceLocation _packageSourceLocation; @@ -55,7 +50,7 @@ internal abstract class InstallingWorkloadCommand : WorkloadCommandBase protected bool UseRollback => !string.IsNullOrWhiteSpace(_fromRollbackDefinition); protected bool FromHistory => _fromHistorySpecified != 0; - protected bool SpecifiedWorkloadSetVersionOnCommandLine => !string.IsNullOrWhiteSpace(_workloadSetVersionFromCommandLine); + protected bool SpecifiedWorkloadSetVersionOnCommandLine => _workloadSetVersionFromCommandLine?.Any() == true; protected bool SpecifiedWorkloadSetVersionInGlobalJson => !string.IsNullOrWhiteSpace(_workloadSetVersionFromGlobalJson); protected WorkloadHistoryState _WorkloadHistoryRecord { @@ -186,7 +181,7 @@ protected void UpdateWorkloadManifests(WorkloadHistoryRecorder recorder, ITransa { // This is essentially the same as updating to a specific workload set version, and we're now past the error check, // so we can just use the same code path. - _workloadSetVersionFromCommandLine = _WorkloadHistoryRecord.WorkloadSetVersion; + _workloadSetVersionFromCommandLine = [_WorkloadHistoryRecord.WorkloadSetVersion]; } else if ((UseRollback || FromHistory) && updateToLatestWorkloadSet) { @@ -214,7 +209,39 @@ protected void UpdateWorkloadManifests(WorkloadHistoryRecorder recorder, ITransa } } - string resolvedWorkloadSetVersion = _workloadSetVersionFromGlobalJson ??_workloadSetVersionFromCommandLine; + string resolvedWorkloadSetVersion = null; + + if (_workloadSetVersionFromCommandLine?.Any(v => v.Contains('@')) == true) + { + var versions = WorkloadSearchVersionsCommand.FindBestWorkloadSetsFromComponents( + _sdkFeatureBand, + _workloadInstaller is not NetSdkMsiInstallerClient ? _workloadInstaller : null, + _sdkFeatureBand.IsPrerelease, + PackageDownloader, + _workloadSetVersionFromCommandLine, + _workloadResolver, + numberOfWorkloadSetsToTake: 1); + + if (versions is null) + { + return; + } + else if (!versions.Any()) + { + Reporter.WriteLine(Update.LocalizableStrings.NoWorkloadUpdateFound); + return; + } + else + { + resolvedWorkloadSetVersion = versions.Single(); + } + } + else if (SpecifiedWorkloadSetVersionOnCommandLine) + { + resolvedWorkloadSetVersion = _workloadSetVersionFromCommandLine.Single(); + } + + resolvedWorkloadSetVersion = _workloadSetVersionFromGlobalJson ?? resolvedWorkloadSetVersion; if (string.IsNullOrWhiteSpace(resolvedWorkloadSetVersion) && !UseRollback && !FromHistory) { _workloadManifestUpdater.UpdateAdvertisingManifestsAsync(_includePreviews, updateToLatestWorkloadSet, offlineCache).Wait(); @@ -441,9 +468,10 @@ protected IEnumerable WriteSDKInstallRecordsForVSWorkloads(IEnumerab internal static class InstallingWorkloadCommandParser { - public static readonly CliOption WorkloadSetVersionOption = new("--version") + public static readonly CliOption> WorkloadSetVersionOption = new("--version") { - Description = Strings.WorkloadSetVersionOptionDescription + Description = Strings.WorkloadSetVersionOptionDescription, + AllowMultipleArgumentsPerToken = true }; public static readonly CliOption PrintDownloadLinkOnlyOption = new("--print-download-link-only") diff --git a/src/Cli/dotnet/commands/dotnet-list/dotnet-list-package/ListPackageReferencesCommand.cs b/src/Cli/dotnet/commands/dotnet-list/dotnet-list-package/ListPackageReferencesCommand.cs index 9ca3b27a500f..cbd10c1016f0 100644 --- a/src/Cli/dotnet/commands/dotnet-list/dotnet-list-package/ListPackageReferencesCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-list/dotnet-list-package/ListPackageReferencesCommand.cs @@ -4,6 +4,7 @@ using System.CommandLine; using Microsoft.DotNet.Cli; using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Tools.Common; using Microsoft.DotNet.Tools.NuGet; namespace Microsoft.DotNet.Tools.List.PackageReferences @@ -71,7 +72,7 @@ private string GetProjectOrSolution() if (Directory.Exists(resultPath)) { - var possibleSolutionPath = Directory.GetFiles(resultPath, "*.sln", SearchOption.TopDirectoryOnly); + string[] possibleSolutionPath = SlnFileFactory.ListSolutionFilesInDirectory(resultPath, false); //If more than a single sln file is found, an error is thrown since we can't determine which one to choose. if (possibleSolutionPath.Count() > 1) diff --git a/src/Cli/dotnet/commands/dotnet-new/PostActions/DotnetSlnPostActionProcessor.cs b/src/Cli/dotnet/commands/dotnet-new/PostActions/DotnetSlnPostActionProcessor.cs index 8321f77d69ed..00c0d66fa6b7 100644 --- a/src/Cli/dotnet/commands/dotnet-new/PostActions/DotnetSlnPostActionProcessor.cs +++ b/src/Cli/dotnet/commands/dotnet-new/PostActions/DotnetSlnPostActionProcessor.cs @@ -25,7 +25,8 @@ public DotnetSlnPostActionProcessor(Func, string?, internal static IReadOnlyList FindSolutionFilesAtOrAbovePath(IPhysicalFileSystem fileSystem, string outputBasePath) { - return FileFindHelpers.FindFilesAtOrAbovePath(fileSystem, outputBasePath, "*.sln"); + return FileFindHelpers.FindFilesAtOrAbovePath(fileSystem, outputBasePath, "*.sln") + ?? FileFindHelpers.FindFilesAtOrAbovePath(fileSystem, outputBasePath, "*.slnx"); } // The project files to add are a subset of the primary outputs, specifically the primary outputs indicated by the primaryOutputIndexes post action argument (semicolon separated) diff --git a/src/Cli/dotnet/commands/dotnet-run/LocalizableStrings.resx b/src/Cli/dotnet/commands/dotnet-run/LocalizableStrings.resx index ca6c5bee84ad..7835c0542477 100644 --- a/src/Cli/dotnet/commands/dotnet-run/LocalizableStrings.resx +++ b/src/Cli/dotnet/commands/dotnet-run/LocalizableStrings.resx @@ -139,6 +139,9 @@ Do not attempt to use launchSettings.json to configure the application. + + Do not use arguments specified in launch profile to run the application. + The configuration to run for. The default for most projects is 'Debug'. diff --git a/src/Cli/dotnet/commands/dotnet-run/Program.cs b/src/Cli/dotnet/commands/dotnet-run/Program.cs index cefc00ba84b6..1dee09851a17 100644 --- a/src/Cli/dotnet/commands/dotnet-run/Program.cs +++ b/src/Cli/dotnet/commands/dotnet-run/Program.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections.Immutable; using System.CommandLine; using Microsoft.DotNet.Cli; using Microsoft.DotNet.Cli.Utils; @@ -58,11 +59,13 @@ public static RunCommand FromParseResult(ParseResult parseResult) projectFileOrDirectory: parseResult.GetValue(RunCommandParser.ProjectOption), launchProfile: parseResult.GetValue(RunCommandParser.LaunchProfileOption), noLaunchProfile: parseResult.HasOption(RunCommandParser.NoLaunchProfileOption), + noLaunchProfileArguments: parseResult.HasOption(RunCommandParser.NoLaunchProfileArgumentsOption), noRestore: parseResult.HasOption(RunCommandParser.NoRestoreOption) || parseResult.HasOption(RunCommandParser.NoBuildOption), interactive: parseResult.HasOption(RunCommandParser.InteractiveOption), verbosity: parseResult.HasOption(CommonOptions.VerbosityOption) ? parseResult.GetValue(CommonOptions.VerbosityOption) : null, - restoreArgs: restoreArgs.ToArray(), - args: nonBinLogArgs.ToArray() + restoreArgs: [.. restoreArgs], + args: [.. nonBinLogArgs], + environmentVariables: parseResult.GetValue(CommonOptions.EnvOption) ?? ImmutableDictionary.Empty ); return command; diff --git a/src/Cli/dotnet/commands/dotnet-run/RunCommand.cs b/src/Cli/dotnet/commands/dotnet-run/RunCommand.cs index 6f802257c3be..e9598d7b1643 100644 --- a/src/Cli/dotnet/commands/dotnet-run/RunCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-run/RunCommand.cs @@ -18,40 +18,55 @@ public partial class RunCommand { private record RunProperties(string? RunCommand, string? RunArguments, string? RunWorkingDirectory); - public bool NoBuild { get; private set; } - public string ProjectFileFullPath { get; private set; } + public bool NoBuild { get; } + public string? ProjectFileOrDirectory { get; } + public string ProjectFileFullPath { get; } public string[] Args { get; set; } - public bool NoRestore { get; private set; } + public bool NoRestore { get; } public VerbosityOptions? Verbosity { get; } - public bool Interactive { get; private set; } - public string[] RestoreArgs { get; private set; } + public bool Interactive { get; } + public string[] RestoreArgs { get; } + + /// + /// Environment variables specified on command line via -e option. + /// + public IReadOnlyDictionary EnvironmentVariables { get; } private bool ShouldBuild => !NoBuild; - public string LaunchProfile { get; private set; } - public bool NoLaunchProfile { get; private set; } - private bool UseLaunchProfile => !NoLaunchProfile; + public string LaunchProfile { get; } + public bool NoLaunchProfile { get; } + + /// + /// True to ignore command line arguments specified by launch profile. + /// + public bool NoLaunchProfileArguments { get; } public RunCommand( bool noBuild, string? projectFileOrDirectory, string launchProfile, bool noLaunchProfile, + bool noLaunchProfileArguments, bool noRestore, bool interactive, VerbosityOptions? verbosity, string[] restoreArgs, - string[] args) + string[] args, + IReadOnlyDictionary environmentVariables) { NoBuild = noBuild; + ProjectFileOrDirectory = projectFileOrDirectory; ProjectFileFullPath = DiscoverProjectFilePath(projectFileOrDirectory); LaunchProfile = launchProfile; NoLaunchProfile = noLaunchProfile; + NoLaunchProfileArguments = noLaunchProfileArguments; Args = args; Interactive = interactive; NoRestore = noRestore; Verbosity = verbosity; RestoreArgs = GetRestoreArguments(restoreArgs); + EnvironmentVariables = environmentVariables; } public int Execute() @@ -74,10 +89,18 @@ public int Execute() try { ICommand targetCommand = GetTargetCommand(); - var launchSettingsCommand = ApplyLaunchSettingsProfileToCommand(targetCommand, launchSettings); + ApplyLaunchSettingsProfileToCommand(targetCommand, launchSettings); + + // Env variables specified on command line override those specified in launch profile: + foreach (var (name, value) in EnvironmentVariables) + { + targetCommand.EnvironmentVariable(name, value); + } + // Ignore Ctrl-C for the remainder of the command's execution Console.CancelKeyPress += (sender, e) => { e.Cancel = true; }; - return launchSettingsCommand.Execute().ExitCode; + + return targetCommand.Execute().ExitCode; } catch (InvalidProjectFileException e) { @@ -87,35 +110,37 @@ public int Execute() } } - private ICommand ApplyLaunchSettingsProfileToCommand(ICommand targetCommand, ProjectLaunchSettingsModel? launchSettings) + private void ApplyLaunchSettingsProfileToCommand(ICommand targetCommand, ProjectLaunchSettingsModel? launchSettings) { - if (launchSettings != null) + if (launchSettings == null) { - if (!string.IsNullOrEmpty(launchSettings.ApplicationUrl)) - { - targetCommand.EnvironmentVariable("ASPNETCORE_URLS", launchSettings.ApplicationUrl); - } + return; + } - targetCommand.EnvironmentVariable("DOTNET_LAUNCH_PROFILE", launchSettings.LaunchProfileName); + if (!string.IsNullOrEmpty(launchSettings.ApplicationUrl)) + { + targetCommand.EnvironmentVariable("ASPNETCORE_URLS", launchSettings.ApplicationUrl); + } - foreach (var entry in launchSettings.EnvironmentVariables) - { - string value = Environment.ExpandEnvironmentVariables(entry.Value); - //NOTE: MSBuild variables are not expanded like they are in VS - targetCommand.EnvironmentVariable(entry.Key, value); - } - if (string.IsNullOrEmpty(targetCommand.CommandArgs) && launchSettings.CommandLineArgs != null) - { - targetCommand.SetCommandArgs(launchSettings.CommandLineArgs); - } + targetCommand.EnvironmentVariable("DOTNET_LAUNCH_PROFILE", launchSettings.LaunchProfileName); + + foreach (var entry in launchSettings.EnvironmentVariables) + { + string value = Environment.ExpandEnvironmentVariables(entry.Value); + //NOTE: MSBuild variables are not expanded like they are in VS + targetCommand.EnvironmentVariable(entry.Key, value); + } + + if (!NoLaunchProfileArguments && string.IsNullOrEmpty(targetCommand.CommandArgs) && launchSettings.CommandLineArgs != null) + { + targetCommand.SetCommandArgs(launchSettings.CommandLineArgs); } - return targetCommand; } private bool TryGetLaunchProfileSettingsIfNeeded(out ProjectLaunchSettingsModel? launchSettingsModel) { launchSettingsModel = default; - if (!UseLaunchProfile) + if (NoLaunchProfile) { return true; } diff --git a/src/Cli/dotnet/commands/dotnet-run/RunCommandParser.cs b/src/Cli/dotnet/commands/dotnet-run/RunCommandParser.cs index f2fff28a7e69..22a6e3784be3 100644 --- a/src/Cli/dotnet/commands/dotnet-run/RunCommandParser.cs +++ b/src/Cli/dotnet/commands/dotnet-run/RunCommandParser.cs @@ -34,6 +34,11 @@ internal static class RunCommandParser Description = LocalizableStrings.CommandOptionNoLaunchProfileDescription }; + public static readonly CliOption NoLaunchProfileArgumentsOption = new("--no-launch-profile-arguments") + { + Description = LocalizableStrings.CommandOptionNoLaunchProfileArgumentsDescription + }; + public static readonly CliOption NoBuildOption = new("--no-build") { Description = LocalizableStrings.CommandOptionNoBuildDescription @@ -81,6 +86,7 @@ private static CliCommand ConstructCommand() command.Options.Add(CommonOptions.OperatingSystemOption); command.Options.Add(CommonOptions.DisableBuildServersOption); command.Options.Add(CommonOptions.ArtifactsPathOption); + command.Options.Add(CommonOptions.EnvOption); command.Arguments.Add(ApplicationArguments); diff --git a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.cs.xlf b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.cs.xlf index ad803e3945c6..59ada52ff3af 100644 --- a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.cs.xlf +++ b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.cs.xlf @@ -17,6 +17,11 @@ K sestavení a spuštění aplikace se použije určená platforma. Tato platforma musí být zadaná v souboru projektu. + + Do not use arguments specified in launch profile to run the application. + Ke spuštění aplikace nepoužívejte argumenty zadané v profilu spuštění. + + The path to the project file to run (defaults to the current directory if there is only one project). Cesta ke spouštěnému souboru projektu (výchozí je aktuální adresář, pokud existuje jenom jeden projekt) diff --git a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.de.xlf b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.de.xlf index 44a232687444..ecec47ebfcae 100644 --- a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.de.xlf +++ b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.de.xlf @@ -17,6 +17,11 @@ Erstellt die App mit dem angegebenen Framework und führt sie aus. Das Framework muss in der Projektdatei angegeben werden. + + Do not use arguments specified in launch profile to run the application. + Verwenden Sie die im Startprofil angegebenen Argumente nicht zum Ausführen der Anwendung. + + The path to the project file to run (defaults to the current directory if there is only one project). Der Pfad zur auszuführenden Projektdatei (standardmäßig das aktuelle Verzeichnis, falls nur ein einzelnes Projekt vorhanden ist). diff --git a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.es.xlf b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.es.xlf index 7f8d692f3ddd..63695e47e069 100644 --- a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.es.xlf +++ b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.es.xlf @@ -17,6 +17,11 @@ Compila y ejecuta la aplicación con la plataforma especificada. La plataforma se debe especificar en el archivo de proyecto. + + Do not use arguments specified in launch profile to run the application. + No use los argumentos especificados en el perfil de inicio para ejecutar la aplicación. + + The path to the project file to run (defaults to the current directory if there is only one project). Ruta de acceso al archivo del proyecto que debe ejecutarse (si solo hay un proyecto, es el directorio actual de forma predeterminada). diff --git a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.fr.xlf b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.fr.xlf index 765e8c7a91eb..286a7a541634 100644 --- a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.fr.xlf +++ b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.fr.xlf @@ -17,6 +17,11 @@ Générez et exécutez l'application à l'aide du framework spécifié. Le framework doit être spécifié dans le fichier projet. + + Do not use arguments specified in launch profile to run the application. + N’utilisez pas les arguments spécifiés dans le profil de lancement pour exécuter l’application. + + The path to the project file to run (defaults to the current directory if there is only one project). Chemin du fichier projet à exécuter (la valeur par défaut est le répertoire actif s'il n'y a qu'un seul projet). diff --git a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.it.xlf b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.it.xlf index 64c2db2f1e9c..5f52c5e48fae 100644 --- a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.it.xlf +++ b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.it.xlf @@ -17,6 +17,11 @@ Consente di compilare ed eseguire l'app con il framework specificato. Il framework deve essere specificato nel file di progetto. + + Do not use arguments specified in launch profile to run the application. + Non utilizzare gli argomenti specificati nel profilo di avvio per eseguire l'applicazione. + + The path to the project file to run (defaults to the current directory if there is only one project). Percorso del file di progetto da eseguire. Se è presente un solo progetto, per impostazione predefinita viene usata la directory corrente. diff --git a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.ja.xlf b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.ja.xlf index c1e3dc0c821d..ab29ec8d15c3 100644 --- a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.ja.xlf +++ b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.ja.xlf @@ -17,6 +17,11 @@ 指定されたフレームワークを使用して、アプリを構築して実行します。フレームワークはプロジェクト ファイルで指定する必要があります。 + + Do not use arguments specified in launch profile to run the application. + 起動プロファイルで指定された引数を使用してアプリケーションを実行しないでください。 + + The path to the project file to run (defaults to the current directory if there is only one project). 実行するプロジェクト ファイルへのパス (プロジェクトが 1 つのみの場合、既定は現在のディレクトリです)。 diff --git a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.ko.xlf b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.ko.xlf index fedd253c635a..a2b77c1bc8bf 100644 --- a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.ko.xlf +++ b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.ko.xlf @@ -17,6 +17,11 @@ 지정된 프레임워크를 사용하여 앱을 빌드 및 실행합니다. 프로젝트 파일에서 프레임워크를 지정해야 합니다. + + Do not use arguments specified in launch profile to run the application. + 시작 프로필에 지정된 인수를 사용하여 애플리케이션을 실행하지 마세요. + + The path to the project file to run (defaults to the current directory if there is only one project). 실행할 프로젝트 파일의 경로입니다(프로젝트가 하나만 있는 경우 현재 디렉터리로 기본 설정됨). diff --git a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.pl.xlf b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.pl.xlf index 36aba105fc80..d013b5a9a62f 100644 --- a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.pl.xlf +++ b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.pl.xlf @@ -17,6 +17,11 @@ Skompiluj i uruchom aplikację przy użyciu określonej platformy. Platforma musi być określona w pliku projektu. + + Do not use arguments specified in launch profile to run the application. + Nie używaj argumentów określonych w profilu uruchamiania do uruchamiania aplikacji. + + The path to the project file to run (defaults to the current directory if there is only one project). Ścieżka do pliku projektu, który ma zostać uruchomiony (w przypadku tylko jednego projektu wartością domyślną jest bieżący katalog). diff --git a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.pt-BR.xlf index 334e435c446c..258d2670d7e7 100644 --- a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.pt-BR.xlf +++ b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.pt-BR.xlf @@ -17,6 +17,11 @@ Compila e executa um aplicativo usando a estrutura especificada. A estrutura deve ser especificada no arquivo de projeto. + + Do not use arguments specified in launch profile to run the application. + Não use argumentos especificados no perfil de inicialização para executar o aplicativo. + + The path to the project file to run (defaults to the current directory if there is only one project). O caminho para o arquivo de projeto a ser executado (usará como padrão o diretório atual se houver apenas um projeto). diff --git a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.ru.xlf b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.ru.xlf index 4d27d2d19ecc..78de4b5ebcd1 100644 --- a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.ru.xlf +++ b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.ru.xlf @@ -17,6 +17,11 @@ Сборка и выполнение приложения с использованием определенной платформы. Платформа должна быть указана в файле проекта. + + Do not use arguments specified in launch profile to run the application. + Не используйте аргументы, указанные в профиле запуска, для запуска приложения. + + The path to the project file to run (defaults to the current directory if there is only one project). Путь к выполняемому файлу проекта (по умолчанию — текущий каталог, если имеется только один проект). diff --git a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.tr.xlf b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.tr.xlf index 3a96699af96c..167786e6277a 100644 --- a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.tr.xlf +++ b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.tr.xlf @@ -17,6 +17,11 @@ Uygulamayı belirtilen çerçeveyi kullanarak derleyin ve çalıştırın. Çerçevenin proje dosyasında belirtilmesi gerekir. + + Do not use arguments specified in launch profile to run the application. + Uygulamayı çalıştırmak için başlatma profilinde belirtilen bağımsız değişkenleri kullanma. + + The path to the project file to run (defaults to the current directory if there is only one project). Çalıştırılacak proje dosyasının yolu (yalnızca bir proje varsa, geçerli dizin varsayılan olarak kullanılır). diff --git a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.zh-Hans.xlf index 995d5b6ab239..799e30f616a5 100644 --- a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.zh-Hans.xlf +++ b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.zh-Hans.xlf @@ -17,6 +17,11 @@ 使用指定的框架生成和运行应用。框架必须在项目文件中指定。 + + Do not use arguments specified in launch profile to run the application. + 不要使用启动配置文件中指定的参数来运行应用程序。 + + The path to the project file to run (defaults to the current directory if there is only one project). 要运行的项目文件的路径(如果只有一个项目,则默认使用当前目录)。 diff --git a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.zh-Hant.xlf index a2aa993f7344..cec07d6b8f89 100644 --- a/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.zh-Hant.xlf +++ b/src/Cli/dotnet/commands/dotnet-run/xlf/LocalizableStrings.zh-Hant.xlf @@ -17,6 +17,11 @@ 使用指定的架構建置及執行應用程式。架構必須在專案檔中指定。 + + Do not use arguments specified in launch profile to run the application. + 不要使用啟動配置檔中指定的自變數來執行應用程式。 + + The path to the project file to run (defaults to the current directory if there is only one project). 要執行之專案檔的路徑 (如果只有一個專案,預設為目前的目錄)。 diff --git a/src/Cli/dotnet/commands/dotnet-sln/SlnCommandParser.cs b/src/Cli/dotnet/commands/dotnet-sln/SlnCommandParser.cs index b2a2f685b752..0155ddd5e203 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/SlnCommandParser.cs +++ b/src/Cli/dotnet/commands/dotnet-sln/SlnCommandParser.cs @@ -47,39 +47,6 @@ private static CliCommand ConstructCommand() return command; } - - internal static string GetSlnFileFullPath(string slnFileOrDirectory) - { - if (File.Exists(slnFileOrDirectory)) - { - return Path.GetFullPath(slnFileOrDirectory); - } - if (Directory.Exists(slnFileOrDirectory)) - { - string[] files = [ - ..Directory.GetFiles(slnFileOrDirectory, "*.sln", SearchOption.TopDirectoryOnly), - ..Directory.GetFiles(slnFileOrDirectory, "*.slnx", SearchOption.TopDirectoryOnly)]; - if (files.Length == 0) - { - throw new GracefulException(CommonLocalizableStrings.CouldNotFindSolutionIn, slnFileOrDirectory); - } - if (files.Length > 1) - { - throw new GracefulException(CommonLocalizableStrings.MoreThanOneSolutionInDirectory, slnFileOrDirectory); - } - return Path.GetFullPath(files.Single()); - } - throw new GracefulException(CommonLocalizableStrings.CouldNotFindSolutionOrDirectory, slnFileOrDirectory); - } - - internal static ISolutionSerializer GetSolutionSerializer(string solutionFilePath) - { - ISolutionSerializer? serializer = SolutionSerializers.GetSerializerByMoniker(solutionFilePath); - if (serializer is null) - { - throw new GracefulException(LocalizableStrings.SerializerNotFound, solutionFilePath); - } - return serializer; - } } + } diff --git a/src/Cli/dotnet/commands/dotnet-sln/add/Program.cs b/src/Cli/dotnet/commands/dotnet-sln/add/Program.cs index e7c7d39e1291..4fee53f6d44d 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/add/Program.cs +++ b/src/Cli/dotnet/commands/dotnet-sln/add/Program.cs @@ -46,7 +46,7 @@ public override int Execute() { throw new GracefulException(CommonLocalizableStrings.SpecifyAtLeastOneProjectToAdd); } - string solutionFileFullPath = SlnCommandParser.GetSlnFileFullPath(_fileOrDirectory); + string solutionFileFullPath = SlnFileFactory.GetSolutionFileFullPath(_fileOrDirectory); try { @@ -73,8 +73,8 @@ public override int Execute() private async Task AddProjectsToSolutionAsync(string solutionFileFullPath, IEnumerable projectPaths, CancellationToken cancellationToken) { - ISolutionSerializer serializer = SlnCommandParser.GetSolutionSerializer(solutionFileFullPath); - SolutionModel solution = await serializer.OpenAsync(solutionFileFullPath, cancellationToken); + SolutionModel solution = SlnFileFactory.CreateFromFileOrDirectory(solutionFileFullPath); + ISolutionSerializer serializer = solution.SerializerExtension.Serializer; // set UTF8 BOM encoding for .sln if (serializer is ISolutionSerializer v12Serializer) { @@ -82,15 +82,15 @@ private async Task AddProjectsToSolutionAsync(string solutionFileFullPath, IEnum { Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: true) }); - } - // Set default configurations and platforms for sln file - foreach (var platform in _defaultPlatforms) - { - solution.AddPlatform(platform); - } - foreach (var buildType in _defaultBuildTypes) - { - solution.AddBuildType(buildType); + // Set default configurations and platforms for sln file + foreach (var platform in _defaultPlatforms) + { + solution.AddPlatform(platform); + } + foreach (var buildType in _defaultBuildTypes) + { + solution.AddBuildType(buildType); + } } SolutionFolderModel? solutionFolder = (!_inRoot && !string.IsNullOrEmpty(_solutionFolderPath)) diff --git a/src/Cli/dotnet/commands/dotnet-sln/list/Program.cs b/src/Cli/dotnet/commands/dotnet-sln/list/Program.cs index 99b948207011..b3957e2bff01 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/list/Program.cs +++ b/src/Cli/dotnet/commands/dotnet-sln/list/Program.cs @@ -3,8 +3,8 @@ using System.CommandLine; using Microsoft.DotNet.Cli; -using Microsoft.DotNet.Cli.Sln.Internal; using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Tools.Common; using Microsoft.VisualStudio.SolutionPersistence; using Microsoft.VisualStudio.SolutionPersistence.Model; using CommandLocalizableStrings = Microsoft.DotNet.Tools.CommonLocalizableStrings; @@ -25,10 +25,10 @@ public ListProjectsInSolutionCommand( public override int Execute() { - string solutionFileFullPath = SlnCommandParser.GetSlnFileFullPath(_fileOrDirectory); + string solutionFileFullPath = SlnFileFactory.GetSolutionFileFullPath(_fileOrDirectory, includeSolutionFilterFiles: true); try { - ListAllProjectsAsync(solutionFileFullPath, CancellationToken.None).Wait(); + ListAllProjectsAsync(solutionFileFullPath); return 0; } catch (Exception ex) @@ -37,10 +37,9 @@ public override int Execute() } } - private async Task ListAllProjectsAsync(string solutionFileFullPath, CancellationToken cancellationToken) + private void ListAllProjectsAsync(string solutionFileFullPath) { - ISolutionSerializer serializer = SlnCommandParser.GetSolutionSerializer(solutionFileFullPath); - SolutionModel solution = await serializer.OpenAsync(solutionFileFullPath, cancellationToken); + SolutionModel solution = SlnFileFactory.CreateFromFileOrDirectory(solutionFileFullPath); string[] paths; if (_displaySolutionFolders) { diff --git a/src/Cli/dotnet/commands/dotnet-sln/migrate/SlnMigrateCommand.cs b/src/Cli/dotnet/commands/dotnet-sln/migrate/SlnMigrateCommand.cs index 1ac8dde1468e..56170cc4992a 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/migrate/SlnMigrateCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-sln/migrate/SlnMigrateCommand.cs @@ -33,7 +33,7 @@ public SlnMigrateCommand( public override int Execute() { - string slnFileFullPath = SlnCommandParser.GetSlnFileFullPath(_slnFileOrDirectory); + string slnFileFullPath = SlnFileFactory.GetSolutionFileFullPath(_slnFileOrDirectory); if (slnFileFullPath.HasExtension(".slnx")) { throw new GracefulException(LocalizableStrings.CannotMigrateSlnx); @@ -50,8 +50,7 @@ public override int Execute() private async Task ConvertToSlnxAsync(string filePath, string slnxFilePath, CancellationToken cancellationToken) { - ISolutionSerializer serializer = SlnCommandParser.GetSolutionSerializer(filePath); - SolutionModel solution = await serializer.OpenAsync(filePath, cancellationToken); + SolutionModel solution = SlnFileFactory.CreateFromFileOrDirectory(filePath); await SolutionSerializers.SlnXml.SaveAsync(slnxFilePath, solution, cancellationToken); _reporter.WriteLine(LocalizableStrings.SlnxGenerated, slnxFilePath); } diff --git a/src/Cli/dotnet/commands/dotnet-sln/remove/Program.cs b/src/Cli/dotnet/commands/dotnet-sln/remove/Program.cs index 766ce64d9b7c..a48ea20f50ce 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/remove/Program.cs +++ b/src/Cli/dotnet/commands/dotnet-sln/remove/Program.cs @@ -19,28 +19,6 @@ internal class RemoveProjectFromSolutionCommand : CommandBase private readonly string _fileOrDirectory; private readonly IReadOnlyCollection _projects; - private int CountNonFolderDescendants( - SolutionModel solution, - SolutionFolderModel item, - Dictionary solutionItemsGroupedByParent, - Dictionary cached) - { - if (cached.ContainsKey(item)) - { - return cached[item]; - } - int count = item.Files?.Count ?? 0; - var children = solutionItemsGroupedByParent.TryGetValue(item, out var items) ? items : Array.Empty(); - foreach (var child in children) - { - count += child is SolutionFolderModel folderModel - ? CountNonFolderDescendants(solution, folderModel, solutionItemsGroupedByParent, cached) - : 1; - } - cached.Add(item, count); - return count; - } - public RemoveProjectFromSolutionCommand(ParseResult parseResult) : base(parseResult) { _fileOrDirectory = parseResult.GetValue(SlnCommandParser.SlnArgument); @@ -52,7 +30,7 @@ public RemoveProjectFromSolutionCommand(ParseResult parseResult) : base(parseRes public override int Execute() { - string solutionFileFullPath = SlnCommandParser.GetSlnFileFullPath(_fileOrDirectory); + string solutionFileFullPath = SlnFileFactory.GetSolutionFileFullPath(_fileOrDirectory); if (_projects.Count == 0) { throw new GracefulException(CommonLocalizableStrings.SpecifyAtLeastOneProjectToRemove); @@ -69,7 +47,7 @@ public override int Execute() ? MsbuildProject.GetProjectFileFromDirectory(fullPath).FullName : fullPath); }); - RemoveProjectsAsync(solutionFileFullPath, relativeProjectPaths, CancellationToken.None).Wait(); + RemoveProjectsAsync(solutionFileFullPath, relativeProjectPaths, CancellationToken.None).GetAwaiter().GetResult(); return 0; } catch (Exception ex) when (ex is not GracefulException) @@ -78,20 +56,16 @@ public override int Execute() { throw new GracefulException(CommonLocalizableStrings.InvalidSolutionFormatString, solutionFileFullPath, ex.Message); } - if (ex.InnerException is GracefulException) - { - throw ex.InnerException; - } throw new GracefulException(ex.Message, ex); } } private async Task RemoveProjectsAsync(string solutionFileFullPath, IEnumerable projectPaths, CancellationToken cancellationToken) { - ISolutionSerializer serializer = SlnCommandParser.GetSolutionSerializer(solutionFileFullPath); - SolutionModel solution = await serializer.OpenAsync(solutionFileFullPath, cancellationToken); + SolutionModel solution = SlnFileFactory.CreateFromFileOrDirectory(solutionFileFullPath); + ISolutionSerializer serializer = solution.SerializerExtension.Serializer; - // set UTF8 BOM encoding for .sln + // set UTF-8 BOM encoding for .sln if (serializer is ISolutionSerializer v12Serializer) { solution.SerializerExtension = v12Serializer.CreateModelExtension(new() @@ -114,21 +88,40 @@ private async Task RemoveProjectsAsync(string solutionFileFullPath, IEnumerable< } } - Dictionary solutionItemsGroupedByParent = solution.SolutionItems - .Where(i => i.Parent != null) - .GroupBy(i => i.Parent) - .ToDictionary(g => g.Key, g => g.ToArray()); - - Dictionary nonFolderDescendantsCount = new(); - foreach (var item in solution.SolutionFolders) + for (int i = 0; i < solution.SolutionFolders.Count; i++) { - CountNonFolderDescendants(solution, item, solutionItemsGroupedByParent, nonFolderDescendantsCount); - } + var folder = solution.SolutionFolders[i]; + int nonFolderDescendants = 0; + Stack stack = new(); + stack.Push(folder); - var emptyFolders = nonFolderDescendantsCount.Where(i => i.Value == 0).Select(i => i.Key); - foreach (var folder in emptyFolders) - { - solution.RemoveFolder(folder); + while (stack.Count > 0) + { + var current = stack.Pop(); + + nonFolderDescendants += current.Files?.Count ?? 0; + foreach (var child in solution.SolutionItems) + { + if (child is { Parent: var parent } && parent == current) + { + if (child is SolutionFolderModel childFolder) + { + stack.Push(childFolder); + } + else + { + nonFolderDescendants++; + } + } + } + } + + if (nonFolderDescendants == 0) + { + solution.RemoveFolder(folder); + // After removal, adjust index and continue to avoid skipping folders after removal + i--; + } } await serializer.SaveAsync(solutionFileFullPath, solution, cancellationToken); diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.cs.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.cs.xlf index f5b32233e7d0..b88b3ff411f1 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.cs.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.cs.xlf @@ -29,7 +29,7 @@ Only .sln files can be migrated to .slnx format. - Only .sln files can be migrated to .slnx format. + Do formátu .slnx lze migrovat pouze .sln soubory. @@ -44,7 +44,7 @@ Generate a .slnx file from a .sln file. - Generate a .slnx file from a .sln file. + Vygeneruje soubor .slnx ze souboru .sln. @@ -69,12 +69,12 @@ Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. - Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Nepovedlo se přečíst {0} souboru řešení. Podporované soubory jsou .sln a platná řešení .slnx. .slnx file {0} generated. - .slnx file {0} generated. + Soubor .slnx {0} vygenerován. diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.de.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.de.xlf index f8eb231f7950..b216ac99c71c 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.de.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.de.xlf @@ -29,7 +29,7 @@ Only .sln files can be migrated to .slnx format. - Only .sln files can be migrated to .slnx format. + Nur .sln Dateien können in das SLNX-Format migriert werden. @@ -44,7 +44,7 @@ Generate a .slnx file from a .sln file. - Generate a .slnx file from a .sln file. + Generiert eine SLNX-Datei aus einer .sln Datei. @@ -69,12 +69,12 @@ Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. - Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Die Projektmappendatei konnte nicht {0} gelesen werden. Unterstützte Dateien sind .sln und SLNX gültige Lösungen. .slnx file {0} generated. - .slnx file {0} generated. + Die SLNX-Datei {0} generiert. diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.es.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.es.xlf index 6ed23a5e39fe..195656606e24 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.es.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.es.xlf @@ -29,7 +29,7 @@ Only .sln files can be migrated to .slnx format. - Only .sln files can be migrated to .slnx format. + Solo se pueden migrar archivos .sln al formato .slnx. @@ -44,7 +44,7 @@ Generate a .slnx file from a .sln file. - Generate a .slnx file from a .sln file. + Generar un archivo .slnx a partir de un archivo .sln. @@ -69,12 +69,12 @@ Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. - Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + No se pudo leer la {0} del archivo de solución. Los archivos admitidos son soluciones válidas .sln y .slnx. .slnx file {0} generated. - .slnx file {0} generated. + {0} generar el archivo .slnx. diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.fr.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.fr.xlf index b1d8c5880aff..25c9c55032dd 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.fr.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.fr.xlf @@ -29,7 +29,7 @@ Only .sln files can be migrated to .slnx format. - Only .sln files can be migrated to .slnx format. + Seuls les fichiers .sln peuvent être migrés au format .slnx. @@ -44,7 +44,7 @@ Generate a .slnx file from a .sln file. - Generate a .slnx file from a .sln file. + Générez un fichier .slnx à partir d’un fichier .sln. @@ -69,12 +69,12 @@ Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. - Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Impossible de lire le fichier solution {0}. Les fichiers pris en charge sont des solutions valides .sln et .slnx. .slnx file {0} generated. - .slnx file {0} generated. + Fichier .slnx {0} généré. diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.it.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.it.xlf index 989a4f33844e..fb7fdb0bd069 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.it.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.it.xlf @@ -29,7 +29,7 @@ Only .sln files can be migrated to .slnx format. - Only .sln files can be migrated to .slnx format. + È possibile eseguire la migrazione al formato slnx solo dei file .sln. @@ -44,7 +44,7 @@ Generate a .slnx file from a .sln file. - Generate a .slnx file from a .sln file. + Genera un file con estensione slnx da un file .sln. @@ -69,12 +69,12 @@ Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. - Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Impossibile leggere il file di soluzione {0}. I file supportati sono soluzioni valide .sln e slnx. .slnx file {0} generated. - .slnx file {0} generated. + Il file con estensione slnx {0} generato. diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ja.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ja.xlf index 2683028f11aa..b44d3d00aa3b 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ja.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ja.xlf @@ -29,7 +29,7 @@ Only .sln files can be migrated to .slnx format. - Only .sln files can be migrated to .slnx format. + .slnx 形式に移行できるのは、.sln ファイルのみです。 @@ -44,7 +44,7 @@ Generate a .slnx file from a .sln file. - Generate a .slnx file from a .sln file. + .sln ファイルから .slnx ファイルを生成します。 @@ -69,12 +69,12 @@ Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. - Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + ソリューション ファイル {0} を読み取ることができませんでした。サポートされているファイルは、.slnおよび .slnx の有効なソリューションです。 .slnx file {0} generated. - .slnx file {0} generated. + .slnx ファイル {0} 生成されました。 diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ko.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ko.xlf index 895400338f29..b27efa5d8fb1 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ko.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ko.xlf @@ -29,7 +29,7 @@ Only .sln files can be migrated to .slnx format. - Only .sln files can be migrated to .slnx format. + .sln 파일만 .slnx 형식으로 마이그레이션할 수 있습니다. @@ -44,7 +44,7 @@ Generate a .slnx file from a .sln file. - Generate a .slnx file from a .sln file. + .sln 파일에서 .slnx 파일을 생성합니다. @@ -69,12 +69,12 @@ Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. - Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + {0} 솔루션 파일을 읽을 수 없습니다. 지원되는 파일은 .sln .slnx 유효한 솔루션입니다. .slnx file {0} generated. - .slnx file {0} generated. + .slnx 파일이 생성되지 {0}. diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.pl.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.pl.xlf index e384d5d00475..bacdde040cfe 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.pl.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.pl.xlf @@ -29,7 +29,7 @@ Only .sln files can be migrated to .slnx format. - Only .sln files can be migrated to .slnx format. + Tylko .sln pliki można migrować do formatu slnx. @@ -44,7 +44,7 @@ Generate a .slnx file from a .sln file. - Generate a .slnx file from a .sln file. + Wygeneruj plik slnx z pliku .sln. @@ -69,12 +69,12 @@ Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. - Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Nie można odczytać {0} pliku rozwiązania. Obsługiwane pliki to prawidłowe rozwiązania .sln i slnx. .slnx file {0} generated. - .slnx file {0} generated. + plik slnx {0} wygenerowany. diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.pt-BR.xlf index ba4d879b8340..6237aac0db8e 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.pt-BR.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.pt-BR.xlf @@ -29,7 +29,7 @@ Only .sln files can be migrated to .slnx format. - Only .sln files can be migrated to .slnx format. + Somente .sln arquivos podem ser migrados para o formato .slnx. @@ -44,7 +44,7 @@ Generate a .slnx file from a .sln file. - Generate a .slnx file from a .sln file. + Gerar um arquivo .slnx a partir de um .sln arquivo. @@ -69,12 +69,12 @@ Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. - Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Não foi possível ler o arquivo de {0}. Os arquivos com suporte são .sln soluções válidas .slnx e válidas. .slnx file {0} generated. - .slnx file {0} generated. + Arquivo .slnx {0} gerado. diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ru.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ru.xlf index c5dfbd52a60c..17207eca647a 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ru.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ru.xlf @@ -29,7 +29,7 @@ Only .sln files can be migrated to .slnx format. - Only .sln files can be migrated to .slnx format. + В формат SLNX можно перенести только .sln файлы. @@ -44,7 +44,7 @@ Generate a .slnx file from a .sln file. - Generate a .slnx file from a .sln file. + Создать SLNX-файл из .sln файла. @@ -69,12 +69,12 @@ Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. - Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Не удалось прочитать файл решения {0}. Поддерживаемые файлы .sln и slnx допустимыми решениями. .slnx file {0} generated. - .slnx file {0} generated. + Файл SLNX {0} создан. diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.tr.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.tr.xlf index fea7bcc4ea34..07c21a22f826 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.tr.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.tr.xlf @@ -29,7 +29,7 @@ Only .sln files can be migrated to .slnx format. - Only .sln files can be migrated to .slnx format. + Yalnızca .sln dosyaları .slnx biçimine geçirilemedi. @@ -44,7 +44,7 @@ Generate a .slnx file from a .sln file. - Generate a .slnx file from a .sln file. + Bir dosyadan .slnx dosyası .sln oluştur. @@ -69,12 +69,12 @@ Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. - Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Çözüm dosyası dosyası {0}. Desteklenen dosyalar .sln .slnx geçerli çözümlerdir. .slnx file {0} generated. - .slnx file {0} generated. + .slnx dosyası {0} değil. diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.zh-Hans.xlf index 82241d2d4a6a..8c96d8369796 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.zh-Hans.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.zh-Hans.xlf @@ -29,7 +29,7 @@ Only .sln files can be migrated to .slnx format. - Only .sln files can be migrated to .slnx format. + 只有.sln文件可以迁移到 .slnx 格式。 @@ -44,7 +44,7 @@ Generate a .slnx file from a .sln file. - Generate a .slnx file from a .sln file. + 从.sln文件生成 .slnx 文件。 @@ -69,12 +69,12 @@ Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. - Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + 无法读取解决方案文件 {0}。受支持的文件是.sln和 .slnx 有效解决方案。 .slnx file {0} generated. - .slnx file {0} generated. + {0} 生成 .slnx 文件。 diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.zh-Hant.xlf index 5b061ec4f5f2..0ebfb6bc8468 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.zh-Hant.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.zh-Hant.xlf @@ -29,7 +29,7 @@ Only .sln files can be migrated to .slnx format. - Only .sln files can be migrated to .slnx format. + 只有.sln檔案可以移轉為 .slnx 格式。 @@ -44,7 +44,7 @@ Generate a .slnx file from a .sln file. - Generate a .slnx file from a .sln file. + 從.sln檔案產生 .slnx 檔案。 @@ -69,12 +69,12 @@ Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. - Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + 無法讀取解決方案檔案 {0}。支援的檔案.sln和 .slnx 有效解決方案。 .slnx file {0} generated. - .slnx file {0} generated. + {0} 產生 .slnx 檔案。 diff --git a/src/Cli/dotnet/commands/dotnet-test/CliConstants.cs b/src/Cli/dotnet/commands/dotnet-test/CliConstants.cs index 8f578b5f31dc..d101a594c6ec 100644 --- a/src/Cli/dotnet/commands/dotnet-test/CliConstants.cs +++ b/src/Cli/dotnet/commands/dotnet-test/CliConstants.cs @@ -22,19 +22,23 @@ internal static class CliConstants public const string TestSectionKey = "test"; - public const string RestoreCommand = "restore"; + public const string RestoreCommand = "Restore"; + public const string BuildCommand = "Build"; + public const string Configuration = "Configuration"; + public const string RuntimeIdentifier = "RuntimeIdentifier"; public static readonly string[] ProjectExtensions = { ".proj", ".csproj", ".vbproj", ".fsproj" }; - public static readonly string[] SolutionExtensions = { ".sln", ".slnx" }; + public static readonly string[] SolutionExtensions = { ".sln", ".slnx", ".slnf" }; public const string ProjectExtensionPattern = "*.*proj"; public const string SolutionExtensionPattern = "*.sln"; public const string SolutionXExtensionPattern = "*.slnx"; + public const string SolutionFilterExtensionPattern = "*.slnf"; public const string BinLogFileName = "msbuild.binlog"; public const string TestingPlatformVsTestBridgeRunSettingsFileEnvVar = "TESTINGPLATFORM_VSTESTBRIDGE_RUNSETTINGS_FILE"; - public const string DLLExtension = "dll"; + public const string DLLExtension = ".dll"; } internal static class TestStates diff --git a/src/Cli/dotnet/commands/dotnet-test/LocalizableStrings.resx b/src/Cli/dotnet/commands/dotnet-test/LocalizableStrings.resx index df9c46f2a035..613f47c7fc95 100644 --- a/src/Cli/dotnet/commands/dotnet-test/LocalizableStrings.resx +++ b/src/Cli/dotnet/commands/dotnet-test/LocalizableStrings.resx @@ -287,22 +287,6 @@ For MSTest before 2.2.4, the timeout is used for all testcases. TIMESPAN - - Sets the value of an environment variable. -Creates the variable if it does not exist, overrides if it does. -This will force the tests to be run in an isolated process. -This argument can be specified multiple times to provide multiple variables. - -Examples: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - - - NAME="VALUE" - No serializer registered with ID '{0}' diff --git a/src/Cli/dotnet/commands/dotnet-test/MSBuildHandler.cs b/src/Cli/dotnet/commands/dotnet-test/MSBuildHandler.cs index b1adead6ad14..c8c107f02eac 100644 --- a/src/Cli/dotnet/commands/dotnet-test/MSBuildHandler.cs +++ b/src/Cli/dotnet/commands/dotnet-test/MSBuildHandler.cs @@ -2,11 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Concurrent; -using Microsoft.Build.Evaluation; -using Microsoft.Build.Execution; -using Microsoft.Build.Framework; -using Microsoft.Build.Logging; +using Microsoft.DotNet.Tools.Common; using Microsoft.DotNet.Tools.Test; +using Microsoft.Testing.Platform.OutputDevice.Terminal; namespace Microsoft.DotNet.Cli { @@ -14,116 +12,73 @@ internal sealed class MSBuildHandler : IDisposable { private readonly List _args; private readonly TestApplicationActionQueue _actionQueue; - private readonly int _degreeOfParallelism; + private TerminalTestReporter _output; private readonly ConcurrentBag _testApplications = new(); private bool _areTestingPlatformApplications = true; - private static readonly Lock buildLock = new(); - - public MSBuildHandler(List args, TestApplicationActionQueue actionQueue, int degreeOfParallelism) + public MSBuildHandler(List args, TestApplicationActionQueue actionQueue, TerminalTestReporter output) { _args = args; _actionQueue = actionQueue; - _degreeOfParallelism = degreeOfParallelism; + _output = output; } - public async Task RunMSBuild(BuildPathsOptions buildPathOptions) + public bool RunMSBuild(BuildOptions buildOptions) { - if (!ValidateBuildPathOptions(buildPathOptions)) + if (!ValidationUtility.ValidateBuildPathOptions(buildOptions, _output)) { return false; } - int msbuildExitCode; + int msBuildExitCode; + string path; - if (!string.IsNullOrEmpty(buildPathOptions.ProjectPath)) + if (!string.IsNullOrEmpty(buildOptions.ProjectPath)) { - msbuildExitCode = await RunBuild(buildPathOptions.ProjectPath, isSolution: false); + path = PathUtility.GetFullPath(buildOptions.ProjectPath); + msBuildExitCode = RunBuild(path, isSolution: false, buildOptions); } - else if (!string.IsNullOrEmpty(buildPathOptions.SolutionPath)) + else if (!string.IsNullOrEmpty(buildOptions.SolutionPath)) { - msbuildExitCode = await RunBuild(buildPathOptions.SolutionPath, isSolution: true); + path = PathUtility.GetFullPath(buildOptions.SolutionPath); + msBuildExitCode = RunBuild(path, isSolution: true, buildOptions); } else { - msbuildExitCode = await RunBuild(buildPathOptions.DirectoryPath ?? Directory.GetCurrentDirectory()); - } - - if (msbuildExitCode != ExitCodes.Success) - { - VSTestTrace.SafeWriteTrace(() => string.Format(LocalizableStrings.CmdMSBuildProjectsPropertiesErrorDescription, msbuildExitCode)); - return false; - } - - return true; - } - - private bool ValidateBuildPathOptions(BuildPathsOptions buildPathOptions) - { - if ((!string.IsNullOrEmpty(buildPathOptions.ProjectPath) && !string.IsNullOrEmpty(buildPathOptions.SolutionPath)) || - (!string.IsNullOrEmpty(buildPathOptions.ProjectPath) && !string.IsNullOrEmpty(buildPathOptions.DirectoryPath)) || - (!string.IsNullOrEmpty(buildPathOptions.SolutionPath) && !string.IsNullOrEmpty(buildPathOptions.DirectoryPath))) - { - VSTestTrace.SafeWriteTrace(() => LocalizableStrings.CmdMultipleBuildPathOptionsErrorDescription); - return false; - } - - if (!string.IsNullOrEmpty(buildPathOptions.ProjectPath)) - { - return ValidateFilePath(buildPathOptions.ProjectPath, CliConstants.ProjectExtensions, LocalizableStrings.CmdInvalidProjectFileExtensionErrorDescription); - } - - if (!string.IsNullOrEmpty(buildPathOptions.SolutionPath)) - { - return ValidateFilePath(buildPathOptions.SolutionPath, CliConstants.SolutionExtensions, LocalizableStrings.CmdInvalidSolutionFileExtensionErrorDescription); + path = PathUtility.GetFullPath(buildOptions.DirectoryPath ?? Directory.GetCurrentDirectory()); + msBuildExitCode = RunBuild(path, buildOptions); } - if (!string.IsNullOrEmpty(buildPathOptions.DirectoryPath) && !Directory.Exists(buildPathOptions.DirectoryPath)) + if (msBuildExitCode != ExitCodes.Success) { - VSTestTrace.SafeWriteTrace(() => string.Format(LocalizableStrings.CmdNonExistentDirectoryErrorDescription, Path.GetFullPath(buildPathOptions.DirectoryPath))); + _output.WriteMessage(string.Format(LocalizableStrings.CmdMSBuildProjectsPropertiesErrorDescription, msBuildExitCode)); return false; } return true; } - private static bool ValidateFilePath(string filePath, string[] validExtensions, string errorMessage) + private int RunBuild(string directoryPath, BuildOptions buildOptions) { - if (!validExtensions.Contains(Path.GetExtension(filePath))) - { - VSTestTrace.SafeWriteTrace(() => string.Format(errorMessage, filePath)); - return false; - } - - if (!File.Exists(filePath)) - { - VSTestTrace.SafeWriteTrace(() => string.Format(LocalizableStrings.CmdNonExistentFileErrorDescription, Path.GetFullPath(filePath))); - return false; - } - - return true; - } - - private async Task RunBuild(string directoryPath) - { - bool solutionOrProjectFileFound = SolutionAndProjectUtility.TryGetProjectOrSolutionFilePath(directoryPath, out string projectOrSolutionFilePath, out bool isSolution); + (bool solutionOrProjectFileFound, string message) = SolutionAndProjectUtility.TryGetProjectOrSolutionFilePath(directoryPath, out string projectOrSolutionFilePath, out bool isSolution); if (!solutionOrProjectFileFound) { + _output.WriteMessage(message); return ExitCodes.GenericFailure; } - (IEnumerable modules, bool restored) = await GetProjectsProperties(projectOrSolutionFilePath, isSolution); + (IEnumerable modules, bool restored) = GetProjectsProperties(projectOrSolutionFilePath, isSolution, buildOptions); InitializeTestApplications(modules); return restored ? ExitCodes.Success : ExitCodes.GenericFailure; } - private async Task RunBuild(string filePath, bool isSolution) + private int RunBuild(string filePath, bool isSolution, BuildOptions buildOptions) { - (IEnumerable modules, bool restored) = await GetProjectsProperties(filePath, isSolution); + (IEnumerable modules, bool restored) = GetProjectsProperties(filePath, isSolution, buildOptions); InitializeTestApplications(modules); @@ -166,187 +121,37 @@ public bool EnqueueTestApplications() return true; } - private async Task<(IEnumerable, bool Restored)> GetProjectsProperties(string solutionOrProjectFilePath, bool isSolution) - { - var allProjects = new ConcurrentBag(); - bool restored = true; - - if (isSolution) - { - string fileDirectory = Path.GetDirectoryName(solutionOrProjectFilePath); - string rootDirectory = string.IsNullOrEmpty(fileDirectory) - ? Directory.GetCurrentDirectory() - : fileDirectory; - - var projects = await SolutionAndProjectUtility.ParseSolution(solutionOrProjectFilePath, rootDirectory); - ProcessProjectsInParallel(projects, allProjects, ref restored); - } - else - { - bool allowBinLog = IsBinaryLoggerEnabled(_args, out string binLogFileName); - - var (relatedProjects, isProjectBuilt) = GetProjectPropertiesInternal(solutionOrProjectFilePath, allowBinLog, binLogFileName); - foreach (var relatedProject in relatedProjects) - { - allProjects.Add(relatedProject); - } - - if (!isProjectBuilt) - { - restored = false; - } - } - return (allProjects, restored); - } - - private void ProcessProjectsInParallel(IEnumerable projects, ConcurrentBag allProjects, ref bool restored) + private (IEnumerable, bool Restored) GetProjectsProperties(string solutionOrProjectFilePath, bool isSolution, BuildOptions buildOptions) { - bool allProjectsRestored = true; - bool allowBinLog = IsBinaryLoggerEnabled(_args, out string binLogFileName); + (IEnumerable allProjects, bool isBuiltOrRestored) = isSolution ? + MSBuildUtility.GetProjectsFromSolution(solutionOrProjectFilePath, buildOptions) : + MSBuildUtility.GetProjectsFromProject(solutionOrProjectFilePath, buildOptions); - Parallel.ForEach( - projects, - new ParallelOptions { MaxDegreeOfParallelism = _degreeOfParallelism }, - () => true, - (project, state, localRestored) => - { - var (relatedProjects, isRestored) = GetProjectPropertiesInternal(project, allowBinLog, binLogFileName); - foreach (var relatedProject in relatedProjects) - { - allProjects.Add(relatedProject); - } - - return localRestored && isRestored; - }, - localRestored => - { - if (!localRestored) - { - allProjectsRestored = false; - } - }); + LogProjectProperties(allProjects); - restored = allProjectsRestored; + return (allProjects, isBuiltOrRestored); } - private static (IEnumerable Modules, bool Restored) GetProjectPropertiesInternal(string projectFilePath, bool allowBinLog, string binLogFileName) + private void LogProjectProperties(IEnumerable modules) { - var projectCollection = new ProjectCollection(); - var project = projectCollection.LoadProject(projectFilePath); - var buildResult = RestoreProject(projectFilePath, projectCollection, allowBinLog, binLogFileName); - - bool restored = buildResult.OverallResult == BuildResultCode.Success; - - if (!restored) + if (!VSTestTrace.TraceEnabled) { - return (Array.Empty(), restored); + return; } - return (ExtractModulesFromProject(project), restored); - } - - private static IEnumerable ExtractModulesFromProject(Project project) - { - _ = bool.TryParse(project.GetPropertyValue(ProjectProperties.IsTestingPlatformApplication), out bool isTestingPlatformApplication); - _ = bool.TryParse(project.GetPropertyValue(ProjectProperties.IsTestProject), out bool isTestProject); - - string targetFramework = project.GetPropertyValue(ProjectProperties.TargetFramework); - string targetFrameworks = project.GetPropertyValue(ProjectProperties.TargetFrameworks); - string targetPath = project.GetPropertyValue(ProjectProperties.TargetPath); - string projectFullPath = project.GetPropertyValue(ProjectProperties.ProjectFullPath); - string runSettingsFilePath = project.GetPropertyValue(ProjectProperties.RunSettingsFilePath); - - var projects = new List(); - - if (string.IsNullOrEmpty(targetFrameworks)) - { - projects.Add(new Module(targetPath, projectFullPath, targetFramework, runSettingsFilePath, isTestingPlatformApplication, isTestProject)); - } - else + foreach (var module in modules) { - var frameworks = targetFrameworks.Split(CliConstants.SemiColon, StringSplitOptions.RemoveEmptyEntries); - foreach (var framework in frameworks) - { - project.SetProperty(ProjectProperties.TargetFramework, framework); - project.ReevaluateIfNecessary(); - - projects.Add(new Module(project.GetPropertyValue(ProjectProperties.TargetPath), - projectFullPath, - framework, - runSettingsFilePath, - isTestingPlatformApplication, - isTestProject)); - } - } + Console.WriteLine(); - return projects; - } - - private static BuildResult RestoreProject(string projectFilePath, ProjectCollection projectCollection, bool allowBinLog, string binLogFileName) - { - BuildParameters parameters = new(projectCollection) - { - Loggers = [new ConsoleLogger(LoggerVerbosity.Quiet)] - }; + VSTestTrace.SafeWriteTrace(() => $"{ProjectProperties.ProjectFullPath}: {module.ProjectFullPath}"); + VSTestTrace.SafeWriteTrace(() => $"{ProjectProperties.IsTestProject}: {module.IsTestProject}"); + VSTestTrace.SafeWriteTrace(() => $"{ProjectProperties.IsTestingPlatformApplication}: {module.IsTestingPlatformApplication}"); + VSTestTrace.SafeWriteTrace(() => $"{ProjectProperties.TargetFramework}: {module.TargetFramework}"); + VSTestTrace.SafeWriteTrace(() => $"{ProjectProperties.TargetPath}: {module.TargetPath}"); + VSTestTrace.SafeWriteTrace(() => $"{ProjectProperties.RunSettingsFilePath}: {module.RunSettingsFilePath}"); - if (allowBinLog) - { - parameters.Loggers = parameters.Loggers.Concat([ - new BinaryLogger - { - Parameters = binLogFileName - } - ]); + Console.WriteLine(); } - - var buildRequestData = new BuildRequestData(projectFilePath, new Dictionary(), null, [CliConstants.RestoreCommand], null); - BuildResult buildResult; - lock (buildLock) - { - buildResult = BuildManager.DefaultBuildManager.Build(parameters, buildRequestData); - } - - return buildResult; - } - - private static bool IsBinaryLoggerEnabled(List args, out string binLogFileName) - { - binLogFileName = string.Empty; - var binLogArgs = new List(); - - foreach (var arg in args) - { - if (arg.StartsWith("/bl:") || arg.Equals("/bl") - || arg.StartsWith("--binaryLogger:") || arg.Equals("--binaryLogger") - || arg.StartsWith("-bl:") || arg.Equals("-bl")) - { - binLogArgs.Add(arg); - - } - } - - if (binLogArgs.Count > 0) - { - // Remove all BinLog args from the list of args - args.RemoveAll(arg => binLogArgs.Contains(arg)); - - // Get BinLog filename - var binLogArg = binLogArgs.LastOrDefault(); - - if (binLogArg.Contains(CliConstants.Colon)) - { - var parts = binLogArg.Split(CliConstants.Colon, 2); - binLogFileName = !string.IsNullOrEmpty(parts[1]) ? parts[1] : CliConstants.BinLogFileName; - } - else - { - binLogFileName = CliConstants.BinLogFileName; - } - - return true; - } - - return false; } public void Dispose() diff --git a/src/Cli/dotnet/commands/dotnet-test/MSBuildUtility.cs b/src/Cli/dotnet/commands/dotnet-test/MSBuildUtility.cs new file mode 100644 index 000000000000..b808312416ee --- /dev/null +++ b/src/Cli/dotnet/commands/dotnet-test/MSBuildUtility.cs @@ -0,0 +1,209 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Concurrent; +using System.Collections.Immutable; +using Microsoft.Build.Evaluation; +using Microsoft.Build.Execution; +using Microsoft.Build.Framework; +using Microsoft.Build.Logging; +using Microsoft.DotNet.Tools.Common; +using Microsoft.VisualStudio.SolutionPersistence.Model; + +namespace Microsoft.DotNet.Cli +{ + internal static class MSBuildUtility + { + public static (IEnumerable, bool) GetProjectsFromSolution(string solutionFilePath, BuildOptions buildOptions) + { + var projectCollection = new ProjectCollection(); + string rootDirectory = SolutionAndProjectUtility.GetRootDirectory(solutionFilePath); + + SolutionModel solutionModel = SlnFileFactory.CreateFromFileOrDirectory(solutionFilePath, includeSolutionFilterFiles: true, includeSolutionXmlFiles: true); + + if (solutionFilePath.HasExtension(".slnf")) + { + solutionFilePath = HandleFilteredSolutionFilePath(solutionFilePath, out rootDirectory); + } + + bool isBuiltOrRestored = BuildOrRestoreProjectOrSolution( + solutionFilePath, + projectCollection, + buildOptions, + GetCommands(buildOptions.HasNoRestore, buildOptions.HasNoBuild)); + + ConcurrentBag projects = GetProjectsProperties(projectCollection, solutionModel.SolutionProjects.Select(p => Path.Combine(rootDirectory, p.FilePath)), buildOptions.DegreeOfParallelism); + return (projects, isBuiltOrRestored); + } + + public static (IEnumerable, bool) GetProjectsFromProject(string projectFilePath, BuildOptions buildOptions) + { + var projectCollection = new ProjectCollection(); + bool isBuiltOrRestored = true; + + if (!buildOptions.HasNoRestore) + { + isBuiltOrRestored = BuildOrRestoreProjectOrSolution( + projectFilePath, + projectCollection, + buildOptions, + [CliConstants.RestoreCommand]); + } + + if (!buildOptions.HasNoBuild) + { + isBuiltOrRestored = isBuiltOrRestored && BuildOrRestoreProjectOrSolution( + projectFilePath, + projectCollection, + buildOptions, + [CliConstants.BuildCommand]); + } + + IEnumerable projects = SolutionAndProjectUtility.GetProjectProperties(projectFilePath, projectCollection); + + return (projects, isBuiltOrRestored); + } + + private static bool BuildOrRestoreProjectOrSolution(string filePath, ProjectCollection projectCollection, BuildOptions buildOptions, string[] commands) + { + var parameters = GetBuildParameters(projectCollection, buildOptions); + var globalProperties = GetGlobalProperties(buildOptions); + + var buildRequestData = new BuildRequestData(filePath, globalProperties, null, commands, null); + + BuildResult buildResult = BuildManager.DefaultBuildManager.Build(parameters, buildRequestData); + + return buildResult.OverallResult == BuildResultCode.Success; + } + + private static ConcurrentBag GetProjectsProperties(ProjectCollection projectCollection, IEnumerable projects, int degreeOfParallelism) + { + var allProjects = new ConcurrentBag(); + + Parallel.ForEach( + projects, + new ParallelOptions { MaxDegreeOfParallelism = degreeOfParallelism }, + (project) => + { + IEnumerable projectsMetadata = SolutionAndProjectUtility.GetProjectProperties(project, projectCollection); + foreach (var projectMetadata in projectsMetadata) + { + allProjects.Add(projectMetadata); + } + }); + + return allProjects; + } + + private static string HandleFilteredSolutionFilePath(string solutionFilterFilePath, out string rootDirectory) + { + string solution = SlnFileFactory.GetSolutionPathFromFilteredSolutionFile(solutionFilterFilePath); + + // Resolve the solution path relative to the .slnf file directory + string solutionFilterDirectory = Path.GetDirectoryName(solutionFilterFilePath); + string solutionFullPath = Path.GetFullPath(solution, solutionFilterDirectory); + rootDirectory = Path.GetDirectoryName(solutionFullPath); + + return solutionFullPath; + } + + internal static bool IsBinaryLoggerEnabled(List args, out string binLogFileName) + { + binLogFileName = string.Empty; + var binLogArgs = new List(); + + foreach (var arg in args) + { + if (arg.StartsWith("/bl:") || arg.Equals("/bl") + || arg.StartsWith("--binaryLogger:") || arg.Equals("--binaryLogger") + || arg.StartsWith("-bl:") || arg.Equals("-bl")) + { + binLogArgs.Add(arg); + + } + } + + if (binLogArgs.Count > 0) + { + // Remove all BinLog args from the list of args + args.RemoveAll(arg => binLogArgs.Contains(arg)); + + // Get BinLog filename + var binLogArg = binLogArgs.LastOrDefault(); + + if (binLogArg.Contains(CliConstants.Colon)) + { + var parts = binLogArg.Split(CliConstants.Colon, 2); + binLogFileName = !string.IsNullOrEmpty(parts[1]) ? parts[1] : CliConstants.BinLogFileName; + } + else + { + binLogFileName = CliConstants.BinLogFileName; + } + + return true; + } + + return false; + } + + private static BuildParameters GetBuildParameters(ProjectCollection projectCollection, BuildOptions buildOptions) + { + BuildParameters parameters = new(projectCollection) + { + Loggers = [new ConsoleLogger(LoggerVerbosity.Quiet)] + }; + + if (!buildOptions.AllowBinLog) + return parameters; + + parameters.Loggers = + [ + .. parameters.Loggers, + .. new[] + { + new BinaryLogger + { + Parameters = buildOptions.BinLogFileName + } + }, + ]; + + return parameters; + } + + private static Dictionary GetGlobalProperties(BuildOptions buildOptions) + { + var globalProperties = new Dictionary(); + + if (!string.IsNullOrEmpty(buildOptions.Configuration)) + { + globalProperties[CliConstants.Configuration] = buildOptions.Configuration; + } + + if (!string.IsNullOrEmpty(buildOptions.RuntimeIdentifier)) + { + globalProperties[CliConstants.RuntimeIdentifier] = buildOptions.RuntimeIdentifier; + } + + return globalProperties; + } + + private static string[] GetCommands(bool hasNoRestore, bool hasNoBuild) + { + var commands = ImmutableArray.CreateBuilder(); + + if (!hasNoRestore) + { + commands.Add(CliConstants.RestoreCommand); + } + + if (!hasNoBuild) + { + commands.Add(CliConstants.BuildCommand); + } + + return [.. commands]; + } + } +} diff --git a/src/Cli/dotnet/commands/dotnet-test/Models.cs b/src/Cli/dotnet/commands/dotnet-test/Models.cs index 17ca6a4261ec..bbfbe4864c3f 100644 --- a/src/Cli/dotnet/commands/dotnet-test/Models.cs +++ b/src/Cli/dotnet/commands/dotnet-test/Models.cs @@ -3,7 +3,7 @@ namespace Microsoft.DotNet.Cli { - internal sealed record Module(string? DllOrExePath, string? ProjectPath, string? TargetFramework, string? RunSettingsFilePath, bool IsTestingPlatformApplication, bool IsTestProject); + internal sealed record Module(string? TargetPath, string? ProjectFullPath, string? TargetFramework, string? RunSettingsFilePath, bool IsTestingPlatformApplication, bool IsTestProject); internal sealed record Handshake(Dictionary? Properties); @@ -20,4 +20,6 @@ internal sealed record FlatException(string? ErrorMessage, string? ErrorType, st internal sealed record FileArtifact(string? FullPath, string? DisplayName, string? Description, string? TestUid, string? TestDisplayName, string? SessionUid); internal sealed record TestSession(byte? SessionType, string? SessionUid, string? ExecutionId); + + internal record MSBuildBuildAndRestoreSettings(string[] Commands, string Configuration, string RuntimeIdentifier, bool AllowBinLog, string BinLogFileName); } diff --git a/src/Cli/dotnet/commands/dotnet-test/Options.cs b/src/Cli/dotnet/commands/dotnet-test/Options.cs index 598e3cb7d722..69789cd3328f 100644 --- a/src/Cli/dotnet/commands/dotnet-test/Options.cs +++ b/src/Cli/dotnet/commands/dotnet-test/Options.cs @@ -3,7 +3,7 @@ namespace Microsoft.DotNet.Cli { - internal record BuildConfigurationOptions(bool HasNoRestore, bool HasNoBuild, bool HasListTests, string Configuration, string Architecture); + internal record BuildConfigurationOptions(bool HasListTests, string Configuration, string Architecture); - internal record BuildPathsOptions(string ProjectPath, string SolutionPath, string DirectoryPath); + internal record BuildOptions(string ProjectPath, string SolutionPath, string DirectoryPath, bool HasNoRestore, bool HasNoBuild, string Configuration, string RuntimeIdentifier, bool AllowBinLog, string BinLogFileName, int DegreeOfParallelism); } diff --git a/src/Cli/dotnet/commands/dotnet-test/Program.cs b/src/Cli/dotnet/commands/dotnet-test/Program.cs index ec586616a4e1..6714489eae66 100644 --- a/src/Cli/dotnet/commands/dotnet-test/Program.cs +++ b/src/Cli/dotnet/commands/dotnet-test/Program.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections.Immutable; using System.CommandLine; using System.Runtime.Versioning; using System.Text.RegularExpressions; @@ -228,8 +229,14 @@ private static TestCommand FromParseResult(ParseResult result, string[] settings noRestore, msbuildPath); - // Apply environment variables provided by the user via --environment (-e) parameter, if present - SetEnvironmentVariablesFromParameters(testCommand, result); + // Apply environment variables provided by the user via --environment (-e) option, if present + if (result.GetValue(CommonOptions.EnvOption) is { } environmentVariables) + { + foreach (var (name, value) in environmentVariables) + { + testCommand.EnvironmentVariable(name, value); + } + } // Set DOTNET_PATH if it isn't already set in the environment as it is required // by the testhost which uses the apphost feature (Windows only). @@ -303,31 +310,6 @@ private static bool ContainsBuiltTestSources(string[] args) return false; } - private static void SetEnvironmentVariablesFromParameters(TestCommand testCommand, ParseResult parseResult) - { - CliOption> option = TestCommandParser.EnvOption; - - if (parseResult.GetResult(option) is null) - { - return; - } - - foreach (string env in parseResult.GetValue(option)) - { - string name = env; - string value = string.Empty; - - int equalsIndex = env.IndexOf('='); - if (equalsIndex > 0) - { - name = env.Substring(0, equalsIndex); - value = env.Substring(equalsIndex + 1); - } - - testCommand.EnvironmentVariable(name, value); - } - } - /// A case-insensitive dictionary of any properties passed from the user and their values. private static Dictionary GetUserSpecifiedExplicitMSBuildProperties(ParseResult parseResult) { diff --git a/src/Cli/dotnet/commands/dotnet-test/SolutionAndProjectUtility.cs b/src/Cli/dotnet/commands/dotnet-test/SolutionAndProjectUtility.cs index a3ca1af6b4c6..02e3bb1b72ea 100644 --- a/src/Cli/dotnet/commands/dotnet-test/SolutionAndProjectUtility.cs +++ b/src/Cli/dotnet/commands/dotnet-test/SolutionAndProjectUtility.cs @@ -1,111 +1,152 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.Build.Evaluation; using Microsoft.DotNet.Tools; -using Microsoft.DotNet.Tools.Test; -using Microsoft.VisualStudio.SolutionPersistence; -using Microsoft.VisualStudio.SolutionPersistence.Model; -using Microsoft.VisualStudio.SolutionPersistence.Serializer; +using Microsoft.DotNet.Tools.Common; +using NuGet.Packaging; +using LocalizableStrings = Microsoft.DotNet.Tools.Test.LocalizableStrings; namespace Microsoft.DotNet.Cli { internal static class SolutionAndProjectUtility { - public static bool TryGetProjectOrSolutionFilePath(string directory, out string projectOrSolutionFilePath, out bool isSolution) + public static (bool SolutionOrProjectFileFound, string Message) TryGetProjectOrSolutionFilePath(string directory, out string projectOrSolutionFilePath, out bool isSolution) { projectOrSolutionFilePath = string.Empty; isSolution = false; if (!Directory.Exists(directory)) { - return false; + return (false, string.Format(LocalizableStrings.CmdNonExistentDirectoryErrorDescription, directory)); } - var possibleSolutionPaths = GetSolutionFilePaths(directory); + var solutionPaths = GetSolutionFilePaths(directory); // If more than a single sln file is found, an error is thrown since we can't determine which one to choose. - if (possibleSolutionPaths.Length > 1) + if (solutionPaths.Length > 1) { - VSTestTrace.SafeWriteTrace(() => string.Format(CommonLocalizableStrings.MoreThanOneSolutionInDirectory, directory)); - return false; + return (false, string.Format(CommonLocalizableStrings.MoreThanOneSolutionInDirectory, directory)); } - if (possibleSolutionPaths.Length == 1) + if (solutionPaths.Length == 1) { - var possibleProjectPaths = GetProjectFilePaths(directory); + var projectPaths = GetProjectFilePaths(directory); - if (possibleProjectPaths.Length == 0) + if (projectPaths.Length == 0) { - projectOrSolutionFilePath = possibleSolutionPaths[0]; + projectOrSolutionFilePath = solutionPaths[0]; isSolution = true; - return true; + return (true, string.Empty); } - VSTestTrace.SafeWriteTrace(() => LocalizableStrings.CmdMultipleProjectOrSolutionFilesErrorDescription); - return false; + return (false, LocalizableStrings.CmdMultipleProjectOrSolutionFilesErrorDescription); } else // If no solutions are found, look for a project file { - string[] possibleProjectPath = GetProjectFilePaths(directory); + string[] projectPaths = GetProjectFilePaths(directory); - if (possibleProjectPath.Length == 0) + if (projectPaths.Length == 0) { - VSTestTrace.SafeWriteTrace(() => LocalizableStrings.CmdNoProjectOrSolutionFileErrorDescription); - return false; + var solutionFilterPaths = GetSolutionFilterFilePaths(directory); + + if (solutionFilterPaths.Length == 0) + { + return (false, LocalizableStrings.CmdNoProjectOrSolutionFileErrorDescription); + } + + if (solutionFilterPaths.Length == 1) + { + projectOrSolutionFilePath = solutionFilterPaths[0]; + isSolution = true; + return (true, string.Empty); + } + else + { + return (false, LocalizableStrings.CmdMultipleProjectOrSolutionFilesErrorDescription); + } } - if (possibleProjectPath.Length == 1) + if (projectPaths.Length == 1) { - projectOrSolutionFilePath = possibleProjectPath[0]; - return true; + projectOrSolutionFilePath = projectPaths[0]; + return (true, string.Empty); } - VSTestTrace.SafeWriteTrace(() => string.Format(CommonLocalizableStrings.MoreThanOneProjectInDirectory, directory)); - - return false; + return (false, string.Format(CommonLocalizableStrings.MoreThanOneSolutionInDirectory, directory)); } } private static string[] GetSolutionFilePaths(string directory) { - return Directory.EnumerateFiles(directory, CliConstants.SolutionExtensionPattern, SearchOption.TopDirectoryOnly) - .Concat(Directory.EnumerateFiles(directory, CliConstants.SolutionXExtensionPattern, SearchOption.TopDirectoryOnly)) - .ToArray(); + string[] solutionFiles = Directory.GetFiles(directory, CliConstants.SolutionExtensionPattern, SearchOption.TopDirectoryOnly); + solutionFiles.AddRange(Directory.GetFiles(directory, CliConstants.SolutionXExtensionPattern, SearchOption.TopDirectoryOnly)); + + return solutionFiles; + } + + private static string[] GetSolutionFilterFilePaths(string directory) + { + return Directory.GetFiles(directory, CliConstants.SolutionFilterExtensionPattern, SearchOption.TopDirectoryOnly); } private static string[] GetProjectFilePaths(string directory) => [.. Directory.EnumerateFiles(directory, CliConstants.ProjectExtensionPattern, SearchOption.TopDirectoryOnly).Where(IsProjectFile)]; private static bool IsProjectFile(string filePath) => CliConstants.ProjectExtensions.Contains(Path.GetExtension(filePath), StringComparer.OrdinalIgnoreCase); - public static async Task> ParseSolution(string solutionFilePath, string directory) + public static string GetRootDirectory(string solutionOrProjectFilePath) + { + string fileDirectory = Path.GetDirectoryName(solutionOrProjectFilePath); + return string.IsNullOrEmpty(fileDirectory) ? Directory.GetCurrentDirectory() : fileDirectory; + } + + public static IEnumerable GetProjectProperties(string projectFilePath, ProjectCollection projectCollection) + { + var project = projectCollection.LoadProject(projectFilePath); + return GetModulesFromProject(project); + } + + private static List GetModulesFromProject(Project project) { - if (string.IsNullOrEmpty(solutionFilePath)) + _ = bool.TryParse(project.GetPropertyValue(ProjectProperties.IsTestProject), out bool isTestProject); + + if (!isTestProject) { - VSTestTrace.SafeWriteTrace(() => $"Solution file path cannot be null or empty: {solutionFilePath}"); return []; } - var projectsPaths = new List(); - SolutionModel solution = null; + _ = bool.TryParse(project.GetPropertyValue(ProjectProperties.IsTestingPlatformApplication), out bool isTestingPlatformApplication); - try - { - solution = SolutionSerializers.GetSerializerByMoniker(solutionFilePath) is ISolutionSerializer serializer - ? await serializer.OpenAsync(solutionFilePath, CancellationToken.None) - : null; - } - catch (Exception ex) + string targetFramework = project.GetPropertyValue(ProjectProperties.TargetFramework); + string targetFrameworks = project.GetPropertyValue(ProjectProperties.TargetFrameworks); + string targetPath = project.GetPropertyValue(ProjectProperties.TargetPath); + string projectFullPath = project.GetPropertyValue(ProjectProperties.ProjectFullPath); + string runSettingsFilePath = project.GetPropertyValue(ProjectProperties.RunSettingsFilePath); + + var projects = new List(); + + if (string.IsNullOrEmpty(targetFrameworks)) { - VSTestTrace.SafeWriteTrace(() => $"Failed to parse solution file '{solutionFilePath}': {ex.Message}"); - return []; + projects.Add(new Module(targetPath, PathUtility.FixFilePath(projectFullPath), targetFramework, runSettingsFilePath, isTestingPlatformApplication, isTestProject)); } - - if (solution is not null) + else { - projectsPaths.AddRange(solution.SolutionProjects.Select(project => Path.Combine(directory, project.FilePath))); + var frameworks = targetFrameworks.Split(CliConstants.SemiColon, StringSplitOptions.RemoveEmptyEntries); + foreach (var framework in frameworks) + { + project.SetProperty(ProjectProperties.TargetFramework, framework); + project.ReevaluateIfNecessary(); + + projects.Add(new Module(project.GetPropertyValue(ProjectProperties.TargetPath), + PathUtility.FixFilePath(projectFullPath), + framework, + runSettingsFilePath, + isTestingPlatformApplication, + isTestProject)); + } } - return projectsPaths; + return projects; } } } diff --git a/src/Cli/dotnet/commands/dotnet-test/Terminal/TerminalTestReporter.cs b/src/Cli/dotnet/commands/dotnet-test/Terminal/TerminalTestReporter.cs index d9c621862c39..ef1e789df7a4 100644 --- a/src/Cli/dotnet/commands/dotnet-test/Terminal/TerminalTestReporter.cs +++ b/src/Cli/dotnet/commands/dotnet-test/Terminal/TerminalTestReporter.cs @@ -47,6 +47,7 @@ internal event EventHandler OnProgressStopUpdate private readonly uint? _originalConsoleMode; private bool _isDiscovery; + private bool _isHelp; private DateTimeOffset? _testExecutionStartTime; private DateTimeOffset? _testExecutionEndTime; @@ -147,9 +148,10 @@ public TerminalTestReporter(IConsole console, TerminalTestReporterOptions option _terminalWithProgress = terminalWithProgress; } - public void TestExecutionStarted(DateTimeOffset testStartTime, int workerCount, bool isDiscovery) + public void TestExecutionStarted(DateTimeOffset testStartTime, int workerCount, bool isDiscovery, bool isHelp) { _isDiscovery = isDiscovery; + _isHelp = isHelp; _testExecutionStartTime = testStartTime; _terminalWithProgress.StartShowingProgress(workerCount); } @@ -189,7 +191,10 @@ public void TestExecutionCompleted(DateTimeOffset endTime) _testExecutionEndTime = endTime; _terminalWithProgress.StopShowingProgress(); - _terminalWithProgress.WriteToTerminal(_isDiscovery ? AppendTestDiscoverySummary : AppendTestRunSummary); + if (!_isHelp) + { + _terminalWithProgress.WriteToTerminal(_isDiscovery ? AppendTestDiscoverySummary : AppendTestRunSummary); + } NativeMethods.RestoreConsoleMode(_originalConsoleMode); _assemblies.Clear(); @@ -757,7 +762,7 @@ internal void AssemblyRunCompleted(string assembly, string? targetFramework, str _terminalWithProgress.RemoveWorker(assemblyRun.SlotIndex); - if (!_isDiscovery && _options.ShowAssembly && _options.ShowAssemblyStartAndComplete) + if (!_isHelp && !_isDiscovery && _options.ShowAssembly && _options.ShowAssemblyStartAndComplete) { _terminalWithProgress.WriteToTerminal(terminal => AppendAssemblySummary(assemblyRun, terminal)); } diff --git a/src/Cli/dotnet/commands/dotnet-test/TestApplication.cs b/src/Cli/dotnet/commands/dotnet-test/TestApplication.cs index 6918d2bcc2a7..5ba3f603ead7 100644 --- a/src/Cli/dotnet/commands/dotnet-test/TestApplication.cs +++ b/src/Cli/dotnet/commands/dotnet-test/TestApplication.cs @@ -31,12 +31,8 @@ internal sealed class TestApplication : IDisposable public event EventHandler SessionEventReceived; public event EventHandler ErrorReceived; public event EventHandler TestProcessExited; - public event EventHandler Run; public event EventHandler ExecutionIdReceived; - private const string TestingPlatformVsTestBridgeRunSettingsFileEnvVar = "TESTINGPLATFORM_VSTESTBRIDGE_RUNSETTINGS_FILE"; - private const string DLLExtension = "dll"; - public Module Module => _module; public TestApplication(Module module, List args) @@ -52,14 +48,12 @@ public void AddExecutionId(string executionId) public async Task RunAsync(bool hasFilterMode, bool enableHelp, BuildConfigurationOptions buildConfigurationOptions) { - Run?.Invoke(this, EventArgs.Empty); - if (hasFilterMode && !ModulePathExists()) { return 1; } - bool isDll = _module.DllOrExePath.HasExtension(CliConstants.DLLExtension); + bool isDll = _module.TargetPath.HasExtension(CliConstants.DLLExtension); var processStartInfo = CreateProcessStartInfo(hasFilterMode, isDll, buildConfigurationOptions, enableHelp); _testAppPipeConnectionLoop = Task.Run(async () => await WaitConnectionAsync(_cancellationToken.Token), _cancellationToken.Token); @@ -75,7 +69,7 @@ private ProcessStartInfo CreateProcessStartInfo(bool hasFilterMode, bool isDll, { var processStartInfo = new ProcessStartInfo { - FileName = hasFilterMode ? (isDll ? Environment.ProcessPath : _module.DllOrExePath) : Environment.ProcessPath, + FileName = hasFilterMode ? (isDll ? Environment.ProcessPath : _module.TargetPath) : Environment.ProcessPath, Arguments = hasFilterMode ? BuildArgs(isDll) : BuildArgsWithDotnetRun(enableHelp, buildConfigurationOptions), RedirectStandardOutput = true, RedirectStandardError = true @@ -89,11 +83,10 @@ private ProcessStartInfo CreateProcessStartInfo(bool hasFilterMode, bool isDll, return processStartInfo; } - private void WaitOnTestApplicationPipeConnectionLoop() { _cancellationToken.Cancel(); - _testAppPipeConnectionLoop.Wait((int)TimeSpan.FromSeconds(30).TotalMilliseconds); + _testAppPipeConnectionLoop?.Wait((int)TimeSpan.FromSeconds(30).TotalMilliseconds); } private async Task WaitConnectionAsync(CancellationToken token) @@ -109,9 +102,14 @@ private async Task WaitConnectionAsync(CancellationToken token) _testAppPipeConnections.Add(pipeConnection); } } - catch (OperationCanceledException ex) when (ex.CancellationToken == token) + catch (OperationCanceledException ex) { // We are exiting + if (VSTestTrace.TraceEnabled) + { + string tokenType = ex.CancellationToken == token ? "internal token" : "external token"; + VSTestTrace.SafeWriteTrace(() => $"WaitConnectionAsync() throws OperationCanceledException with {tokenType}"); + } } catch (Exception ex) { @@ -212,7 +210,7 @@ private async Task StartProcess(ProcessStartInfo processStartInfo) { if (VSTestTrace.TraceEnabled) { - VSTestTrace.SafeWriteTrace(() => $"Updated args: {processStartInfo.Arguments}"); + VSTestTrace.SafeWriteTrace(() => $"Test application arguments: {processStartInfo.Arguments}"); } var process = Process.Start(processStartInfo); @@ -248,9 +246,9 @@ private void StoreOutputAndErrorData(Process process) private bool ModulePathExists() { - if (!File.Exists(_module.DllOrExePath)) + if (!File.Exists(_module.TargetPath)) { - ErrorReceived.Invoke(this, new ErrorEventArgs { ErrorMessage = $"Test module '{_module.DllOrExePath}' not found. Build the test application before or run 'dotnet test'." }); + ErrorReceived.Invoke(this, new ErrorEventArgs { ErrorMessage = $"Test module '{_module.TargetPath}' not found. Build the test application before or run 'dotnet test'." }); return false; } return true; @@ -260,17 +258,11 @@ private string BuildArgsWithDotnetRun(bool hasHelp, BuildConfigurationOptions bu { StringBuilder builder = new(); - builder.Append($"{CliConstants.DotnetRunCommand} {TestingPlatformOptions.ProjectOption.Name} \"{_module.ProjectPath}\""); + builder.Append($"{CliConstants.DotnetRunCommand} {TestingPlatformOptions.ProjectOption.Name} \"{_module.ProjectFullPath}\""); - if (buildConfigurationOptions.HasNoRestore) - { - builder.Append($" {TestingPlatformOptions.NoRestoreOption.Name}"); - } - - if (buildConfigurationOptions.HasNoBuild) - { - builder.Append($" {TestingPlatformOptions.NoBuildOption.Name}"); - } + // Because we restored and built before in MSHandler, we will skip those with dotnet run + builder.Append($" {TestingPlatformOptions.NoRestoreOption.Name}"); + builder.Append($" {TestingPlatformOptions.NoBuildOption.Name}"); if (buildConfigurationOptions.HasListTests) { @@ -314,7 +306,7 @@ private string BuildArgs(bool isDll) if (isDll) { - builder.Append($"exec {_module.DllOrExePath} "); + builder.Append($"exec {_module.TargetPath} "); } builder.Append(_args.Count != 0 @@ -331,7 +323,7 @@ public void OnHandshakeMessage(HandshakeMessage handshakeMessage) if (handshakeMessage.Properties.TryGetValue(HandshakeMessagePropertyNames.ExecutionId, out string executionId)) { AddExecutionId(executionId); - ExecutionIdReceived?.Invoke(this, new ExecutionEventArgs { ModulePath = _module.DllOrExePath, ExecutionId = executionId }); + ExecutionIdReceived?.Invoke(this, new ExecutionEventArgs { ModulePath = _module.TargetPath, ExecutionId = executionId }); } HandshakeReceived?.Invoke(this, new HandshakeArgs { Handshake = new Handshake(handshakeMessage.Properties) }); } @@ -374,20 +366,22 @@ public override string ToString() { StringBuilder builder = new(); - if (!string.IsNullOrEmpty(_module.DllOrExePath)) + if (!string.IsNullOrEmpty(_module.TargetPath)) { - builder.Append($"DLL: {_module.DllOrExePath}"); + builder.Append($"DLL: {_module.TargetPath}"); } - if (!string.IsNullOrEmpty(_module.ProjectPath)) + if (!string.IsNullOrEmpty(_module.ProjectFullPath)) { - builder.Append($"Project: {_module.ProjectPath}"); - }; + builder.Append($"Project: {_module.ProjectFullPath}"); + } + ; if (!string.IsNullOrEmpty(_module.TargetFramework)) { builder.Append($"Target Framework: {_module.TargetFramework}"); - }; + } + ; return builder.ToString(); } diff --git a/src/Cli/dotnet/commands/dotnet-test/TestApplicationEventHandlers.cs b/src/Cli/dotnet/commands/dotnet-test/TestApplicationEventHandlers.cs new file mode 100644 index 000000000000..4a93abd53184 --- /dev/null +++ b/src/Cli/dotnet/commands/dotnet-test/TestApplicationEventHandlers.cs @@ -0,0 +1,219 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Concurrent; +using Microsoft.DotNet.Tools.Test; +using Microsoft.Testing.Platform.OutputDevice; +using Microsoft.Testing.Platform.OutputDevice.Terminal; + +namespace Microsoft.DotNet.Cli +{ + internal sealed class TestApplicationsEventHandlers + { + private readonly ConcurrentDictionary _executions; + private readonly TerminalTestReporter _output; + + public TestApplicationsEventHandlers( + ConcurrentDictionary executions, + TerminalTestReporter output) + { + _executions = executions; + _output = output; + } + + public void OnHandshakeReceived(object sender, HandshakeArgs args) + { + var testApplication = (TestApplication)sender; + var executionId = args.Handshake.Properties[HandshakeMessagePropertyNames.ExecutionId]; + var arch = args.Handshake.Properties[HandshakeMessagePropertyNames.Architecture]?.ToLower(); + var tfm = TargetFrameworkParser.GetShortTargetFramework(args.Handshake.Properties[HandshakeMessagePropertyNames.Framework]); + (string ModulePath, string TargetFramework, string Architecture, string ExecutionId) appInfo = new(testApplication.Module.TargetPath, tfm, arch, executionId); + _executions[testApplication] = appInfo; + _output.AssemblyRunStarted(appInfo.ModulePath, appInfo.TargetFramework, appInfo.Architecture, appInfo.ExecutionId); + + if (!VSTestTrace.TraceEnabled) return; + + foreach (var property in args.Handshake.Properties) + { + VSTestTrace.SafeWriteTrace(() => $"{GetHandshakePropertyName(property.Key)}: {property.Value}"); + } + } + + private static string GetHandshakePropertyName(byte propertyId) => + propertyId switch + { + HandshakeMessagePropertyNames.PID => nameof(HandshakeMessagePropertyNames.PID), + HandshakeMessagePropertyNames.Architecture => nameof(HandshakeMessagePropertyNames.Architecture), + HandshakeMessagePropertyNames.Framework => nameof(HandshakeMessagePropertyNames.Framework), + HandshakeMessagePropertyNames.OS => nameof(HandshakeMessagePropertyNames.OS), + HandshakeMessagePropertyNames.SupportedProtocolVersions => nameof(HandshakeMessagePropertyNames.SupportedProtocolVersions), + HandshakeMessagePropertyNames.HostType => nameof(HandshakeMessagePropertyNames.HostType), + HandshakeMessagePropertyNames.ModulePath => nameof(HandshakeMessagePropertyNames.ModulePath), + HandshakeMessagePropertyNames.ExecutionId => nameof(HandshakeMessagePropertyNames.ExecutionId), + _ => string.Empty, + }; + + public void OnDiscoveredTestsReceived(object sender, DiscoveredTestEventArgs args) + { + var testApp = (TestApplication)sender; + var appInfo = _executions[testApp]; + + foreach (var test in args.DiscoveredTests) + { + _output.TestDiscovered(appInfo.ModulePath, appInfo.TargetFramework, appInfo.Architecture, appInfo.ExecutionId, + test.DisplayName, + test.Uid); + } + + if (!VSTestTrace.TraceEnabled) return; + + VSTestTrace.SafeWriteTrace(() => $"DiscoveredTests Execution Id: {args.ExecutionId}"); + foreach (var discoveredTestMessage in args.DiscoveredTests) + { + VSTestTrace.SafeWriteTrace(() => $"DiscoveredTest: {discoveredTestMessage.Uid}, {discoveredTestMessage.DisplayName}"); + } + } + + public void OnTestResultsReceived(object sender, TestResultEventArgs args) + { + foreach (var testResult in args.SuccessfulTestResults) + { + var testApp = (TestApplication)sender; + var appInfo = _executions[testApp]; + _output.TestCompleted(appInfo.ModulePath, appInfo.TargetFramework, appInfo.Architecture, appInfo.ExecutionId, + testResult.Uid, + testResult.DisplayName, + ToOutcome(testResult.State), + TimeSpan.FromTicks(testResult.Duration ?? 0), + exceptions: null, + expected: null, + actual: null, + standardOutput: null, + errorOutput: null); + } + + foreach (var testResult in args.FailedTestResults) + { + var testApp = (TestApplication)sender; + var appInfo = _executions[testApp]; + _output.TestCompleted(appInfo.ModulePath, appInfo.TargetFramework, appInfo.Architecture, appInfo.ExecutionId, + testResult.Uid, + testResult.DisplayName, + ToOutcome(testResult.State), + TimeSpan.FromTicks(testResult.Duration ?? 0), + exceptions: testResult.Exceptions.Select(fe => new Microsoft.Testing.Platform.OutputDevice.Terminal.FlatException(fe.ErrorMessage, fe.ErrorType, fe.StackTrace)).ToArray(), + expected: null, + actual: null, + standardOutput: null, + errorOutput: null); + } + + if (!VSTestTrace.TraceEnabled) return; + + VSTestTrace.SafeWriteTrace(() => $"TestResults Execution Id: {args.ExecutionId}"); + + foreach (SuccessfulTestResult successfulTestResult in args.SuccessfulTestResults) + { + VSTestTrace.SafeWriteTrace(() => $"SuccessfulTestResult: {successfulTestResult.Uid}, {successfulTestResult.DisplayName}, " + + $"{successfulTestResult.State}, {successfulTestResult.Duration}, {successfulTestResult.Reason}, {successfulTestResult.StandardOutput}," + + $"{successfulTestResult.ErrorOutput}, {successfulTestResult.SessionUid}"); + } + + foreach (FailedTestResult failedTestResult in args.FailedTestResults) + { + VSTestTrace.SafeWriteTrace(() => $"FailedTestResult: {failedTestResult.Uid}, {failedTestResult.DisplayName}, " + + $"{failedTestResult.State}, {failedTestResult.Duration}, {failedTestResult.Reason}, {string.Join(", ", failedTestResult.Exceptions?.Select(e => $"{e.ErrorMessage}, {e.ErrorType}, {e.StackTrace}"))}" + + $"{failedTestResult.StandardOutput}, {failedTestResult.ErrorOutput}, {failedTestResult.SessionUid}"); + } + } + + public void OnFileArtifactsReceived(object sender, FileArtifactEventArgs args) + { + var testApp = (TestApplication)sender; + var appInfo = _executions[testApp]; + + foreach (var artifact in args.FileArtifacts) + { + _output.ArtifactAdded( + outOfProcess: false, + appInfo.ModulePath, appInfo.TargetFramework, appInfo.Architecture, appInfo.ExecutionId, + artifact.TestDisplayName, artifact.FullPath); + } + + if (!VSTestTrace.TraceEnabled) return; + + VSTestTrace.SafeWriteTrace(() => $"FileArtifactMessages Execution Id: {args.ExecutionId}"); + + foreach (FileArtifact fileArtifactMessage in args.FileArtifacts) + { + VSTestTrace.SafeWriteTrace(() => $"FileArtifact: {fileArtifactMessage.FullPath}, {fileArtifactMessage.DisplayName}, " + + $"{fileArtifactMessage.Description}, {fileArtifactMessage.TestUid}, {fileArtifactMessage.TestDisplayName}, " + + $"{fileArtifactMessage.SessionUid}"); + } + } + + public void OnSessionEventReceived(object sender, SessionEventArgs args) + { + if (!VSTestTrace.TraceEnabled) return; + + var sessionEvent = args.SessionEvent; + VSTestTrace.SafeWriteTrace(() => $"TestSessionEvent: {sessionEvent.SessionType}, {sessionEvent.SessionUid}, {sessionEvent.ExecutionId}"); + } + + public void OnErrorReceived(object sender, ErrorEventArgs args) + { + if (!VSTestTrace.TraceEnabled) return; + + VSTestTrace.SafeWriteTrace(() => args.ErrorMessage); + } + + public void OnTestProcessExited(object sender, TestProcessExitEventArgs args) + { + var testApplication = (TestApplication)sender; + + if (_executions.TryGetValue(testApplication, out var appInfo)) + { + _output.AssemblyRunCompleted(appInfo.ModulePath, appInfo.TargetFramework, appInfo.Architecture, appInfo.ExecutionId, args.ExitCode, string.Join(Environment.NewLine, args.OutputData), string.Join(Environment.NewLine, args.ErrorData)); + } + else + { + _output.AssemblyRunCompleted(testApplication.Module.TargetPath ?? testApplication.Module.ProjectFullPath, testApplication.Module.TargetFramework, architecture: null, null, args.ExitCode, string.Join(Environment.NewLine, args.OutputData), string.Join(Environment.NewLine, args.ErrorData)); + } + + if (!VSTestTrace.TraceEnabled) return; + + if (args.ExitCode != ExitCodes.Success) + { + VSTestTrace.SafeWriteTrace(() => $"Test Process exited with non-zero exit code: {args.ExitCode}"); + } + + if (args.OutputData.Count > 0) + { + VSTestTrace.SafeWriteTrace(() => $"Output Data: {string.Join("\n", args.OutputData)}"); + } + + if (args.ErrorData.Count > 0) + { + VSTestTrace.SafeWriteTrace(() => $"Error Data: {string.Join("\n", args.ErrorData)}"); + } + } + + public void OnExecutionIdReceived(object sender, ExecutionEventArgs args) + { + } + + public static TestOutcome ToOutcome(byte? testState) + { + return testState switch + { + TestStates.Passed => TestOutcome.Passed, + TestStates.Skipped => TestOutcome.Skipped, + TestStates.Failed => TestOutcome.Fail, + TestStates.Error => TestOutcome.Error, + TestStates.Timeout => TestOutcome.Timeout, + TestStates.Cancelled => TestOutcome.Canceled, + _ => throw new ArgumentOutOfRangeException(nameof(testState), $"Invalid test state value {testState}") + }; + } + } +} diff --git a/src/Cli/dotnet/commands/dotnet-test/TestCommandParser.cs b/src/Cli/dotnet/commands/dotnet-test/TestCommandParser.cs index df414cbfa4e9..3ce15d512dbf 100644 --- a/src/Cli/dotnet/commands/dotnet-test/TestCommandParser.cs +++ b/src/Cli/dotnet/commands/dotnet-test/TestCommandParser.cs @@ -22,12 +22,6 @@ internal static class TestCommandParser Description = LocalizableStrings.CmdListTestsDescription }.ForwardAs("-property:VSTestListTests=true"); - public static readonly CliOption> EnvOption = new CliOption>("--environment", "-e") - { - Description = LocalizableStrings.CmdEnvironmentVariableDescription, - HelpName = LocalizableStrings.CmdEnvironmentVariableExpression - }.AllowSingleArgPerToken(); - public static readonly CliOption FilterOption = new ForwardedOption("--filter") { Description = LocalizableStrings.CmdTestCaseFilterDescription, @@ -168,9 +162,6 @@ private static bool IsTestingPlatformEnabled() private static CliCommand ConstructCommand() { -#if RELEASE - return GetVSTestCliCommand(); -#else bool isTestingPlatformEnabled = IsTestingPlatformEnabled(); string testingSdkName = isTestingPlatformEnabled ? "testingplatform" : "vstest"; @@ -184,7 +175,6 @@ private static CliCommand ConstructCommand() } throw new InvalidOperationException($"Testing sdk not supported: {testingSdkName}"); -#endif } private static CliCommand GetTestingPlatformCliCommand() @@ -219,7 +209,7 @@ private static CliCommand GetVSTestCliCommand() command.Options.Add(SettingsOption); command.Options.Add(ListTestsOption); - command.Options.Add(EnvOption); + command.Options.Add(CommonOptions.EnvOption); command.Options.Add(FilterOption); command.Options.Add(AdapterOption); command.Options.Add(LoggerOption); diff --git a/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.cs b/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.cs index e73dddebf244..5fb118ff256e 100644 --- a/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.cs @@ -1,30 +1,28 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Collections.Concurrent; using System.CommandLine; using Microsoft.DotNet.Tools.Test; using Microsoft.TemplateEngine.Cli.Commands; using Microsoft.Testing.Platform.Helpers; -using Microsoft.Testing.Platform.OutputDevice; using Microsoft.Testing.Platform.OutputDevice.Terminal; namespace Microsoft.DotNet.Cli { internal partial class TestingPlatformCommand : CliCommand, ICustomHelp { - private readonly ConcurrentBag _testApplications = []; - private MSBuildHandler _msBuildHandler; private TestModulesFilterHandler _testModulesFilterHandler; private TerminalTestReporter _output; private bool _isHelp; + private int _degreeOfParallelism; private TestApplicationActionQueue _actionQueue; private List _args; private ConcurrentDictionary _executions = new(); private byte _cancelled; private bool _isDiscovery; + private TestApplicationsEventHandlers _eventHandlers; public TestingPlatformCommand(string name, string description = null) : base(name, description) { @@ -36,107 +34,49 @@ public int Run(ParseResult parseResult) bool hasFailed = false; try { - Console.CancelKeyPress += (s, e) => - { - _output?.StartCancelling(); - CompleteRun(); - }; + SetupCancelKeyPressHandler(); - int degreeOfParallelism = GetDegreeOfParallelism(parseResult); + _degreeOfParallelism = GetDegreeOfParallelism(parseResult); BuildConfigurationOptions buildConfigurationOptions = GetBuildConfigurationOptions(parseResult); - InitializeActionQueue(parseResult, degreeOfParallelism, buildConfigurationOptions); - - bool filterModeEnabled = parseResult.HasOption(TestingPlatformOptions.TestModulesFilterOption); - - if (filterModeEnabled && parseResult.HasOption(TestingPlatformOptions.ArchitectureOption)) - { - VSTestTrace.SafeWriteTrace(() => $"The --arch option is not supported yet."); - } - - if (parseResult.HasOption(TestingPlatformOptions.ListTestsOption)) - { - _isDiscovery = true; - } - BuildConfigurationOptions builtInOptions = new( - parseResult.HasOption(TestingPlatformOptions.NoRestoreOption), - parseResult.HasOption(TestingPlatformOptions.NoBuildOption), - parseResult.HasOption(TestingPlatformOptions.ListTestsOption), - parseResult.GetValue(TestingPlatformOptions.ConfigurationOption), - parseResult.GetValue(TestingPlatformOptions.ArchitectureOption)); + _isDiscovery = parseResult.HasOption(TestingPlatformOptions.ListTestsOption); + _args = [.. parseResult.UnmatchedTokens]; + _isHelp = ContainsHelpOption(parseResult.GetArguments()); - var console = new SystemConsole(); - var output = new TerminalTestReporter(console, new TerminalTestReporterOptions() - { - ShowPassedTests = Environment.GetEnvironmentVariable("SHOW_PASSED") == "1" ? () => true : () => false, - ShowProgress = () => Environment.GetEnvironmentVariable("NO_PROGRESS") != "1", - UseAnsi = Environment.GetEnvironmentVariable("NO_ANSI") != "1", - ShowAssembly = true, - ShowAssemblyStartAndComplete = true, - }); - _output = output; + InitializeOutput(_degreeOfParallelism); - _isHelp = false; - if (ContainsHelpOption(parseResult.GetArguments())) + bool filterModeEnabled = parseResult.HasOption(TestingPlatformOptions.TestModulesFilterOption); + if (_isHelp) { - _isHelp = true; - _actionQueue = new(degreeOfParallelism, async (TestApplication testApp) => - { - testApp.HelpRequested += OnHelpRequested; - testApp.ErrorReceived += OnErrorReceived; - testApp.TestProcessExited += OnTestProcessExited; - testApp.Run += OnTestApplicationRun; - testApp.ExecutionIdReceived += OnExecutionIdReceived; - - var result = await testApp.RunAsync(filterModeEnabled, enableHelp: true, builtInOptions); - return result; - }); + InitializeHelpActionQueue(_degreeOfParallelism, buildConfigurationOptions, filterModeEnabled); } else { - _output.TestExecutionStarted(DateTimeOffset.Now, degreeOfParallelism, _isDiscovery); - - _actionQueue = new(degreeOfParallelism, async (TestApplication testApp) => - { - testApp.HandshakeReceived += OnHandshakeReceived; - testApp.DiscoveredTestsReceived += OnDiscoveredTestsReceived; - testApp.TestResultsReceived += OnTestResultsReceived; - testApp.FileArtifactsReceived += OnFileArtifactsReceived; - testApp.SessionEventReceived += OnSessionEventReceived; - testApp.ErrorReceived += OnErrorReceived; - testApp.TestProcessExited += OnTestProcessExited; - testApp.Run += OnTestApplicationRun; - testApp.ExecutionIdReceived += OnExecutionIdReceived; - - return await testApp.RunAsync(filterModeEnabled, enableHelp: false, builtInOptions); - }); + InitializeTestExecutionActionQueue(_degreeOfParallelism, buildConfigurationOptions, filterModeEnabled); } - _args = [.. parseResult.UnmatchedTokens]; - _msBuildHandler = new(_args, _actionQueue, degreeOfParallelism); + _msBuildHandler = new(_args, _actionQueue, _output); _testModulesFilterHandler = new(_args, _actionQueue); - if (parseResult.HasOption(TestingPlatformOptions.TestModulesFilterOption)) + _eventHandlers = new TestApplicationsEventHandlers(_executions, _output); + + if (filterModeEnabled) { if (!_testModulesFilterHandler.RunWithTestModulesFilter(parseResult)) { - CompleteRun(); return ExitCodes.GenericFailure; } } else { - var buildPathOptions = GetBuildPathOptions(parseResult); - if (!_msBuildHandler.RunMSBuild(buildPathOptions).GetAwaiter().GetResult()) + if (!_msBuildHandler.RunMSBuild(GetBuildOptions(parseResult))) { - CompleteRun(); return ExitCodes.GenericFailure; } if (!_msBuildHandler.EnqueueTestApplications()) { - VSTestTrace.SafeWriteTrace(() => LocalizableStrings.CmdUnsupportedVSTestTestApplicationsDescription); - CompleteRun(); + _output.WriteMessage(LocalizableStrings.CmdUnsupportedVSTestTestApplicationsDescription); return ExitCodes.GenericFailure; } } @@ -146,278 +86,117 @@ public int Run(ParseResult parseResult) } finally { + CompleteRun(); CleanUp(); } - CompleteRun(); return hasFailed ? ExitCodes.GenericFailure : ExitCodes.Success; } - private static int GetDegreeOfParallelism(ParseResult parseResult) - { - if (!int.TryParse(parseResult.GetValue(TestingPlatformOptions.MaxParallelTestModulesOption), out int degreeOfParallelism) || degreeOfParallelism <= 0) - degreeOfParallelism = Environment.ProcessorCount; - return degreeOfParallelism; - } - - private static BuildConfigurationOptions GetBuildConfigurationOptions(ParseResult parseResult) => - new(parseResult.HasOption(TestingPlatformOptions.NoRestoreOption), - parseResult.HasOption(TestingPlatformOptions.NoBuildOption), - parseResult.HasOption(TestingPlatformOptions.ListTestsOption), - parseResult.GetValue(TestingPlatformOptions.ConfigurationOption), - parseResult.GetValue(TestingPlatformOptions.ArchitectureOption)); - - private static BuildPathsOptions GetBuildPathOptions(ParseResult parseResult) => - new(parseResult.GetValue(TestingPlatformOptions.ProjectOption), - parseResult.GetValue(TestingPlatformOptions.SolutionOption), - parseResult.GetValue(TestingPlatformOptions.DirectoryOption)); - - private void InitializeActionQueue(ParseResult parseResult, int degreeOfParallelism, BuildConfigurationOptions buildConfigurationOptions) - { - if (!ContainsHelpOption(parseResult.GetArguments())) - { - _actionQueue = new(degreeOfParallelism, async (TestApplication testApp) => - { - testApp.HandshakeReceived += OnHandshakeReceived; - testApp.DiscoveredTestsReceived += OnDiscoveredTestsReceived; - testApp.TestResultsReceived += OnTestResultsReceived; - testApp.FileArtifactsReceived += OnFileArtifactsReceived; - testApp.SessionEventReceived += OnSessionEventReceived; - testApp.ErrorReceived += OnErrorReceived; - testApp.TestProcessExited += OnTestProcessExited; - testApp.Run += OnTestApplicationRun; - testApp.ExecutionIdReceived += OnExecutionIdReceived; - - return await testApp.RunAsync(hasFilterMode: false, enableHelp: false, buildConfigurationOptions); - }); - } - else - { - _actionQueue = new(degreeOfParallelism, async (TestApplication testApp) => - { - testApp.HelpRequested += OnHelpRequested; - testApp.ErrorReceived += OnErrorReceived; - testApp.TestProcessExited += OnTestProcessExited; - testApp.Run += OnTestApplicationRun; - testApp.ExecutionIdReceived += OnExecutionIdReceived; - - return await testApp.RunAsync(hasFilterMode: true, enableHelp: true, buildConfigurationOptions); - }); - } - } - - private static bool ContainsHelpOption(IEnumerable args) => args.Contains(CliConstants.HelpOptionKey) || args.Contains(CliConstants.HelpOptionKey.Substring(0, 2)); - - private void CompleteRun() + private void SetupCancelKeyPressHandler() { - if (Interlocked.CompareExchange(ref _cancelled, 1, 0) == 0) + Console.CancelKeyPress += (s, e) => { - if (!_isHelp) - { - _output?.TestExecutionCompleted(DateTimeOffset.Now); - } - } + _output?.StartCancelling(); + CompleteRun(); + }; } - private void CleanUp() + private void InitializeOutput(int degreeOfParallelism) { - _msBuildHandler.Dispose(); - foreach (var testApplication in _testApplications) + var console = new SystemConsole(); + _output = new TerminalTestReporter(console, new TerminalTestReporterOptions() { - testApplication.Dispose(); - } - } - - private void OnHandshakeReceived(object sender, HandshakeArgs args) - { - var testApplication = (TestApplication)sender; - var executionId = args.Handshake.Properties[HandshakeMessagePropertyNames.ExecutionId]; - var arch = args.Handshake.Properties[HandshakeMessagePropertyNames.Architecture]?.ToLower(); - var tfm = TargetFrameworkParser.GetShortTargetFramework(args.Handshake.Properties[HandshakeMessagePropertyNames.Framework]); - (string ModulePath, string TargetFramework, string Architecture, string ExecutionId) appInfo = new(testApplication.Module.DllOrExePath, tfm, arch, executionId); - _executions[testApplication] = appInfo; - _output.AssemblyRunStarted(appInfo.ModulePath, appInfo.TargetFramework, appInfo.Architecture, appInfo.ExecutionId); + ShowPassedTests = Environment.GetEnvironmentVariable("SHOW_PASSED") == "1" ? () => true : () => false, + ShowProgress = () => Environment.GetEnvironmentVariable("NO_PROGRESS") != "1", + UseAnsi = Environment.GetEnvironmentVariable("NO_ANSI") != "1", + ShowAssembly = true, + ShowAssemblyStartAndComplete = true, + }); - if (!VSTestTrace.TraceEnabled) return; - - foreach (var property in args.Handshake.Properties) + if (!_isHelp) { - VSTestTrace.SafeWriteTrace(() => $"{property.Key}: {property.Value}"); + _output.TestExecutionStarted(DateTimeOffset.Now, degreeOfParallelism, _isDiscovery, _isHelp); } } - private void OnDiscoveredTestsReceived(object sender, DiscoveredTestEventArgs args) + private void InitializeHelpActionQueue(int degreeOfParallelism, BuildConfigurationOptions buildConfigurationOptions, bool filterModeEnabled) { - var testApp = (TestApplication)sender; - var appInfo = _executions[testApp]; - - foreach (var test in args.DiscoveredTests) + _actionQueue = new(degreeOfParallelism, async (TestApplication testApp) => { - _output.TestDiscovered(appInfo.ModulePath, appInfo.TargetFramework, appInfo.Architecture, appInfo.ExecutionId, - test.DisplayName, - test.Uid); - } + testApp.HelpRequested += OnHelpRequested; + testApp.ErrorReceived += _eventHandlers.OnErrorReceived; + testApp.TestProcessExited += _eventHandlers.OnTestProcessExited; + testApp.ExecutionIdReceived += _eventHandlers.OnExecutionIdReceived; - if (!VSTestTrace.TraceEnabled) return; - - VSTestTrace.SafeWriteTrace(() => $"DiscoveredTests Execution Id: {args.ExecutionId}"); - foreach (var discoveredTestMessage in args.DiscoveredTests) - { - VSTestTrace.SafeWriteTrace(() => $"DiscoveredTest: {discoveredTestMessage.Uid}, {discoveredTestMessage.DisplayName}"); - } + return await testApp.RunAsync(filterModeEnabled, enableHelp: true, buildConfigurationOptions); + }); } - private void OnTestResultsReceived(object sender, TestResultEventArgs args) + private void InitializeTestExecutionActionQueue(int degreeOfParallelism, BuildConfigurationOptions buildConfigurationOptions, bool filterModeEnabled) { - foreach (var testResult in args.SuccessfulTestResults) - { - var testApp = (TestApplication)sender; - var appInfo = _executions[testApp]; - _output.TestCompleted(appInfo.ModulePath, appInfo.TargetFramework, appInfo.Architecture, appInfo.ExecutionId, - testResult.Uid, - testResult.DisplayName, - ToOutcome(testResult.State), - TimeSpan.FromTicks(testResult.Duration ?? 0), - exceptions: null, - expected: null, - actual: null, - standardOutput: null, - errorOutput: null); - } - - foreach (var testResult in args.FailedTestResults) - { - var testApp = (TestApplication)sender; - // TODO: expected - // TODO: actual - var appInfo = _executions[testApp]; - _output.TestCompleted(appInfo.ModulePath, appInfo.TargetFramework, appInfo.Architecture, appInfo.ExecutionId, - testResult.Uid, - testResult.DisplayName, - ToOutcome(testResult.State), - TimeSpan.FromTicks(testResult.Duration ?? 0), - exceptions: testResult.Exceptions.Select(fe => new Microsoft.Testing.Platform.OutputDevice.Terminal.FlatException(fe.ErrorMessage, fe.ErrorType, fe.StackTrace)).ToArray(), - expected: null, - actual: null, - standardOutput: null, - errorOutput: null); - } - - if (!VSTestTrace.TraceEnabled) return; - - VSTestTrace.SafeWriteTrace(() => $"TestResults Execution Id: {args.ExecutionId}"); - - foreach (SuccessfulTestResult successfulTestResult in args.SuccessfulTestResults) + _actionQueue = new(degreeOfParallelism, async (TestApplication testApp) => { - VSTestTrace.SafeWriteTrace(() => $"SuccessfulTestResult: {successfulTestResult.Uid}, {successfulTestResult.DisplayName}, " + - $"{successfulTestResult.State}, {successfulTestResult.Duration}, {successfulTestResult.Reason}, {successfulTestResult.StandardOutput}," + - $"{successfulTestResult.ErrorOutput}, {successfulTestResult.SessionUid}"); - } + testApp.HandshakeReceived += _eventHandlers.OnHandshakeReceived; + testApp.DiscoveredTestsReceived += _eventHandlers.OnDiscoveredTestsReceived; + testApp.TestResultsReceived += _eventHandlers.OnTestResultsReceived; + testApp.FileArtifactsReceived += _eventHandlers.OnFileArtifactsReceived; + testApp.SessionEventReceived += _eventHandlers.OnSessionEventReceived; + testApp.ErrorReceived += _eventHandlers.OnErrorReceived; + testApp.TestProcessExited += _eventHandlers.OnTestProcessExited; + testApp.ExecutionIdReceived += _eventHandlers.OnExecutionIdReceived; - foreach (FailedTestResult failedTestResult in args.FailedTestResults) - { - VSTestTrace.SafeWriteTrace(() => $"FailedTestResult: {failedTestResult.Uid}, {failedTestResult.DisplayName}, " + - $"{failedTestResult.State}, {failedTestResult.Duration}, {failedTestResult.Reason}, {string.Join(", ", failedTestResult.Exceptions?.Select(e => $"{e.ErrorMessage}, {e.ErrorType}, {e.StackTrace}"))}" + - $"{failedTestResult.StandardOutput}, {failedTestResult.ErrorOutput}, {failedTestResult.SessionUid}"); - } + return await testApp.RunAsync(filterModeEnabled, enableHelp: false, buildConfigurationOptions); + }); } - public static TestOutcome ToOutcome(byte? testState) + private static int GetDegreeOfParallelism(ParseResult parseResult) { - return testState switch - { - TestStates.Passed => TestOutcome.Passed, - TestStates.Skipped => TestOutcome.Skipped, - TestStates.Failed => TestOutcome.Fail, - TestStates.Error => TestOutcome.Error, - TestStates.Timeout => TestOutcome.Timeout, - TestStates.Cancelled => TestOutcome.Canceled, - _ => throw new ArgumentOutOfRangeException(nameof(testState), $"Invalid test state value {testState}") - }; + if (!int.TryParse(parseResult.GetValue(TestingPlatformOptions.MaxParallelTestModulesOption), out int degreeOfParallelism) || degreeOfParallelism <= 0) + degreeOfParallelism = Environment.ProcessorCount; + return degreeOfParallelism; } - private void OnFileArtifactsReceived(object sender, FileArtifactEventArgs args) - { - var testApp = (TestApplication)sender; - var appInfo = _executions[testApp]; - - foreach (var artifact in args.FileArtifacts) - { - // TODO: Is artifact out of process - _output.ArtifactAdded( - outOfProcess: false, - appInfo.ModulePath, appInfo.TargetFramework, appInfo.Architecture, appInfo.ExecutionId, - artifact.TestDisplayName, artifact.FullPath); - } - - if (!VSTestTrace.TraceEnabled) return; - - VSTestTrace.SafeWriteTrace(() => $"FileArtifactMessages Execution Id: {args.ExecutionId}"); - - foreach (FileArtifact fileArtifactMessage in args.FileArtifacts) - { - VSTestTrace.SafeWriteTrace(() => $"FileArtifact: {fileArtifactMessage.FullPath}, {fileArtifactMessage.DisplayName}, " + - $"{fileArtifactMessage.Description}, {fileArtifactMessage.TestUid}, {fileArtifactMessage.TestDisplayName}, " + - $"{fileArtifactMessage.SessionUid}"); - } - } + private static BuildConfigurationOptions GetBuildConfigurationOptions(ParseResult parseResult) => + new(parseResult.HasOption(TestingPlatformOptions.ListTestsOption), + parseResult.GetValue(TestingPlatformOptions.ConfigurationOption), + parseResult.GetValue(TestingPlatformOptions.ArchitectureOption)); - private void OnSessionEventReceived(object sender, SessionEventArgs args) + private BuildOptions GetBuildOptions(ParseResult parseResult) { - if (!VSTestTrace.TraceEnabled) return; + bool allowBinLog = MSBuildUtility.IsBinaryLoggerEnabled([.. parseResult.UnmatchedTokens], out string binLogFileName); - var sessionEvent = args.SessionEvent; - VSTestTrace.SafeWriteTrace(() => $"TestSessionEvent: {sessionEvent.SessionType}, {sessionEvent.SessionUid}, {sessionEvent.ExecutionId}"); + return new BuildOptions(parseResult.GetValue(TestingPlatformOptions.ProjectOption), + parseResult.GetValue(TestingPlatformOptions.SolutionOption), + parseResult.GetValue(TestingPlatformOptions.DirectoryOption), + parseResult.HasOption(TestingPlatformOptions.NoRestoreOption), + parseResult.HasOption(TestingPlatformOptions.NoBuildOption), + parseResult.GetValue(TestingPlatformOptions.ConfigurationOption), + parseResult.HasOption(TestingPlatformOptions.ArchitectureOption) ? + CommonOptions.ResolveRidShorthandOptionsToRuntimeIdentifier(string.Empty, parseResult.GetValue(TestingPlatformOptions.ArchitectureOption)) : + string.Empty, + allowBinLog, + binLogFileName, + _degreeOfParallelism); } - private void OnErrorReceived(object sender, ErrorEventArgs args) - { - if (!VSTestTrace.TraceEnabled) return; - - VSTestTrace.SafeWriteTrace(() => args.ErrorMessage); - } + private static bool ContainsHelpOption(IEnumerable args) => args.Contains(CliConstants.HelpOptionKey) || args.Contains(CliConstants.HelpOptionKey.Substring(0, 2)); - private void OnTestProcessExited(object sender, TestProcessExitEventArgs args) + private void CompleteRun() { - var testApplication = (TestApplication)sender; - - // If the application exits too early we might not start the execution, - // e.g. if the parameter is incorrect. - if (_executions.TryGetValue(testApplication, out var appInfo)) - { - _output.AssemblyRunCompleted(appInfo.ModulePath, appInfo.TargetFramework, appInfo.Architecture, appInfo.ExecutionId, args.ExitCode, string.Join(Environment.NewLine, args.OutputData), string.Join(Environment.NewLine, args.ErrorData)); - } - else - { - _output.AssemblyRunCompleted(testApplication.Module.DllOrExePath ?? testApplication.Module.ProjectPath, testApplication.Module.TargetFramework, architecture: null, null, args.ExitCode, string.Join(Environment.NewLine, args.OutputData), string.Join(Environment.NewLine, args.ErrorData)); - } - - if (!VSTestTrace.TraceEnabled) return; - - if (args.ExitCode != ExitCodes.Success) - { - VSTestTrace.SafeWriteTrace(() => $"Test Process exited with non-zero exit code: {args.ExitCode}"); - } - - if (args.OutputData.Count > 0) - { - VSTestTrace.SafeWriteTrace(() => $"Output Data: {string.Join("\n", args.OutputData)}"); - } - - if (args.ErrorData.Count > 0) + if (Interlocked.CompareExchange(ref _cancelled, 1, 0) == 0) { - VSTestTrace.SafeWriteTrace(() => $"Error Data: {string.Join("\n", args.ErrorData)}"); + _output?.TestExecutionCompleted(DateTimeOffset.Now); } } - private void OnTestApplicationRun(object sender, EventArgs args) - { - TestApplication testApp = sender as TestApplication; - _testApplications.Add(testApp); - } - - private void OnExecutionIdReceived(object sender, ExecutionEventArgs args) + private void CleanUp() { + _msBuildHandler.Dispose(); + foreach (var execution in _executions) + { + execution.Key.Dispose(); + } } } } diff --git a/src/Cli/dotnet/commands/dotnet-test/ValidationUtility.cs b/src/Cli/dotnet/commands/dotnet-test/ValidationUtility.cs new file mode 100644 index 000000000000..efb5d3996de3 --- /dev/null +++ b/src/Cli/dotnet/commands/dotnet-test/ValidationUtility.cs @@ -0,0 +1,57 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.DotNet.Tools.Test; +using Microsoft.Testing.Platform.OutputDevice.Terminal; + +namespace Microsoft.DotNet.Cli +{ + internal static class ValidationUtility + { + public static bool ValidateBuildPathOptions(BuildOptions buildPathOptions, TerminalTestReporter output) + { + if ((!string.IsNullOrEmpty(buildPathOptions.ProjectPath) && !string.IsNullOrEmpty(buildPathOptions.SolutionPath)) || + (!string.IsNullOrEmpty(buildPathOptions.ProjectPath) && !string.IsNullOrEmpty(buildPathOptions.DirectoryPath)) || + (!string.IsNullOrEmpty(buildPathOptions.SolutionPath) && !string.IsNullOrEmpty(buildPathOptions.DirectoryPath))) + { + output.WriteMessage(LocalizableStrings.CmdMultipleBuildPathOptionsErrorDescription); + return false; + } + + if (!string.IsNullOrEmpty(buildPathOptions.ProjectPath)) + { + return ValidateFilePath(buildPathOptions.ProjectPath, CliConstants.ProjectExtensions, LocalizableStrings.CmdInvalidProjectFileExtensionErrorDescription, output); + } + + if (!string.IsNullOrEmpty(buildPathOptions.SolutionPath)) + { + return ValidateFilePath(buildPathOptions.SolutionPath, CliConstants.SolutionExtensions, LocalizableStrings.CmdInvalidSolutionFileExtensionErrorDescription, output); + } + + if (!string.IsNullOrEmpty(buildPathOptions.DirectoryPath) && !Directory.Exists(buildPathOptions.DirectoryPath)) + { + output.WriteMessage(string.Format(LocalizableStrings.CmdNonExistentDirectoryErrorDescription, buildPathOptions.DirectoryPath)); + return false; + } + + return true; + } + + private static bool ValidateFilePath(string filePath, string[] validExtensions, string errorMessage, TerminalTestReporter output) + { + if (!validExtensions.Contains(Path.GetExtension(filePath))) + { + output.WriteMessage(string.Format(errorMessage, filePath)); + return false; + } + + if (!File.Exists(filePath)) + { + output.WriteMessage(string.Format(LocalizableStrings.CmdNonExistentFileErrorDescription, Path.GetFullPath(filePath))); + return false; + } + + return true; + } + } +} diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.cs.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.cs.xlf index 1a467d0ffc2e..5232acc9dae7 100644 --- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.cs.xlf +++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.cs.xlf @@ -118,36 +118,6 @@ Pro MSTest před 2.2.4 se časový limit použije pro všechny testovací příp Defines the path of directory to run. If not specified, it defaults to the current directory. - - Sets the value of an environment variable. -Creates the variable if it does not exist, overrides if it does. -This will force the tests to be run in an isolated process. -This argument can be specified multiple times to provide multiple variables. - -Examples: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - Nastaví hodnotu proměnné prostředí. -Pokud proměnná neexistuje, vytvoří ji, a pokud existuje, přepíše ji. -Tímto se vynutí spuštění testů v izolovaném procesu. -Tento argument je možné zadat vícekrát a určit tak více proměnných. - -Příklady: --e PROMĚNNÁ=abc --e PROMĚNNÁ="hodnota s mezerami" --e PROMĚNNÁ="hodnota;oddělená;pomocí;středníků" --e PROM1=abc -e PROM2=def -e PROM3=ghi - - - - - NAME="VALUE" - NÁZEV="HODNOTA" - - The provided project file has an invalid extension: {0}. The provided project file has an invalid extension: {0}. diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.de.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.de.xlf index 7f363065066d..07f28f763619 100644 --- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.de.xlf +++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.de.xlf @@ -118,36 +118,6 @@ für MSTest vor 2.2.4 wird das Timeout für alle Testfälle verwendet. Defines the path of directory to run. If not specified, it defaults to the current directory. - - Sets the value of an environment variable. -Creates the variable if it does not exist, overrides if it does. -This will force the tests to be run in an isolated process. -This argument can be specified multiple times to provide multiple variables. - -Examples: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - Legt den Wert einer Umgebungsvariablen fest. -Erstellt die Variable, wenn Sie nicht vorhanden ist, und setzt sie andernfalls außer Kraft. -Dadurch wird die Ausführung der Tests in einem isolierten Prozess erzwungen. -Dieses Argument kann mehrmals angegeben werden, um mehrere Variablen bereitzustellen. - -Beispiele: --e VARIABLE=abc --e VARIABLE="wert mit leerzeichen" --e VARIABLE="wert;getrennt durch;semikolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - - - - NAME="VALUE" - NAME="WERT" - - The provided project file has an invalid extension: {0}. The provided project file has an invalid extension: {0}. diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.es.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.es.xlf index 759ad3d5c656..f1e79eedeea6 100644 --- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.es.xlf +++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.es.xlf @@ -120,36 +120,6 @@ Para MSTest antes de 2.2.4, el tiempo de espera se usa para todos los casos de p Defines the path of directory to run. If not specified, it defaults to the current directory. - - Sets the value of an environment variable. -Creates the variable if it does not exist, overrides if it does. -This will force the tests to be run in an isolated process. -This argument can be specified multiple times to provide multiple variables. - -Examples: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - Establece el valor de una variable de entorno. -Crea la variable si no existe o la reemplaza en caso de que exista. -Esto forzará la ejecución de las pruebas en un proceso aislado. -Este argumento se puede especificar varias veces para proporcionar múltiples variables. - -Ejemplos: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - - - - NAME="VALUE" - NAME="VALUE" - - The provided project file has an invalid extension: {0}. The provided project file has an invalid extension: {0}. diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.fr.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.fr.xlf index 158ab5127a98..5ae2232e016b 100644 --- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.fr.xlf +++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.fr.xlf @@ -118,36 +118,6 @@ Pour MSTest avant la version 2.2.4, le délai d’expiration est utilisé pour Defines the path of directory to run. If not specified, it defaults to the current directory. - - Sets the value of an environment variable. -Creates the variable if it does not exist, overrides if it does. -This will force the tests to be run in an isolated process. -This argument can be specified multiple times to provide multiple variables. - -Examples: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - Définit la valeur d'une variable d'environnement. -Crée la variable si elle n'existe pas, et la remplace si elle existe. -Cela entraîne l'exécution forcée des tests dans un processus isolé. -Vous pouvez spécifier cet argument plusieurs fois pour fournir plusieurs variables. - -Exemples : --e VARIABLE=abc --e VARIABLE="valeur avec des espaces" --e VARIABLE="valeur;séparée;par;des;points;virgules" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - - - - NAME="VALUE" - NAME="VALUE" - - The provided project file has an invalid extension: {0}. The provided project file has an invalid extension: {0}. diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.it.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.it.xlf index 19be826da372..49d98e288b86 100644 --- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.it.xlf +++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.it.xlf @@ -118,36 +118,6 @@ Per MSTest prima di 2.2.4, il timeout viene usato per tutti i test case.Defines the path of directory to run. If not specified, it defaults to the current directory. - - Sets the value of an environment variable. -Creates the variable if it does not exist, overrides if it does. -This will force the tests to be run in an isolated process. -This argument can be specified multiple times to provide multiple variables. - -Examples: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - Imposta il valore di una variabile di ambiente. -Crea la variabile se non esiste e la sostituisce se esiste. -In questo modo forza l'esecuzione dei test in un processo isolato. -È possibile specificare più volte questo argomento per fornire più variabili. - -Esempi: --e VARIABLE=abc --e VARIABLE="valore con spazi" --e VARIABLE="valore;delimitato da;punti e virgola" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - - - - NAME="VALUE" - NAME="VALORE" - - The provided project file has an invalid extension: {0}. The provided project file has an invalid extension: {0}. diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ja.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ja.xlf index 2a42214138ea..cee3b0dc4092 100644 --- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ja.xlf +++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ja.xlf @@ -118,36 +118,6 @@ MSTest 2.2.4 以前の場合、タイムアウトはすべてのテスト ケー Defines the path of directory to run. If not specified, it defaults to the current directory. - - Sets the value of an environment variable. -Creates the variable if it does not exist, overrides if it does. -This will force the tests to be run in an isolated process. -This argument can be specified multiple times to provide multiple variables. - -Examples: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - 環境変数の値を設定します。 -変数が存在しない場合は作成され、存在する場合はオーバーライドされます。 -これにより、テストは強制的に分離プロセスで実行されます。 -この引数は、複数の変数を指定するために複数回指定できます。 - -例: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - - - - NAME="VALUE" - NAME="VALUE" - - The provided project file has an invalid extension: {0}. The provided project file has an invalid extension: {0}. diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ko.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ko.xlf index 9d51e9159532..4ca212886e5d 100644 --- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ko.xlf +++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ko.xlf @@ -118,36 +118,6 @@ For MSTest before 2.2.4, the timeout is used for all testcases. Defines the path of directory to run. If not specified, it defaults to the current directory. - - Sets the value of an environment variable. -Creates the variable if it does not exist, overrides if it does. -This will force the tests to be run in an isolated process. -This argument can be specified multiple times to provide multiple variables. - -Examples: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - 환경 변수의 값을 설정합니다. -변수가 없는 경우 변수를 만들고, 변수가 있으면 재정의합니다. -이는 테스트가 격리된 프로세스에서 강제로 실행되도록 합니다. -이 인수를 여러 번 지정하여 여러 변수를 제공할 수 있습니다. - -예: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - - - - NAME="VALUE" - NAME="VALUE" - - The provided project file has an invalid extension: {0}. The provided project file has an invalid extension: {0}. diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.pl.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.pl.xlf index b4ebe3500c92..06dc75aeec0e 100644 --- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.pl.xlf +++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.pl.xlf @@ -118,36 +118,6 @@ W przypadku platformy MSTest przed wersją 2.2.4 limit czasu jest używany dla w Defines the path of directory to run. If not specified, it defaults to the current directory. - - Sets the value of an environment variable. -Creates the variable if it does not exist, overrides if it does. -This will force the tests to be run in an isolated process. -This argument can be specified multiple times to provide multiple variables. - -Examples: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - Ustawia wartość zmiennej środowiskowej. -Jeśli zmienna nie istnieje, tworzy ją, a jeśli istnieje, przesłania. -Wymusi to uruchamianie testów w izolowanym procesie. -Ten argument można określić wiele razy w celu podania wielu wartości. - -Przykłady: --e ZMIENNA=abc --e ZMIENNA="wartość ze spacjami" --e ZMIENNA="wartości;rozdzielone;średnikami" --e ZM1=abc -e ZM2=def -e ZM3=ghi - - - - - NAME="VALUE" - NAZWA="WARTOŚĆ" - - The provided project file has an invalid extension: {0}. The provided project file has an invalid extension: {0}. diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.pt-BR.xlf index c4f3190d52e3..fbff9cc212eb 100644 --- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.pt-BR.xlf +++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.pt-BR.xlf @@ -118,36 +118,6 @@ Para MSTest antes de 2.2.4, o tempo limite é usado para todos os casos de teste Defines the path of directory to run. If not specified, it defaults to the current directory. - - Sets the value of an environment variable. -Creates the variable if it does not exist, overrides if it does. -This will force the tests to be run in an isolated process. -This argument can be specified multiple times to provide multiple variables. - -Examples: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - Define o valor de uma variável de ambiente. -Criará a variável quando ela não existir e a substituirá quando existir. -Isso forçará a execução dos testes em um processo isolado. -Esse argumento pode ser especificado várias vezes para fornecer várias variáveis. - -Exemplos: --e VARIABLE=abc --e VARIABLE="valor com espaços" --e VARIABLE="valor;separado com;ponto e vírgula" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - - - - NAME="VALUE" - NAME="VALUE" - - The provided project file has an invalid extension: {0}. The provided project file has an invalid extension: {0}. diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ru.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ru.xlf index 74c94acd1e44..e92b6da91bbe 100644 --- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ru.xlf +++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ru.xlf @@ -118,36 +118,6 @@ For MSTest before 2.2.4, the timeout is used for all testcases. Defines the path of directory to run. If not specified, it defaults to the current directory. - - Sets the value of an environment variable. -Creates the variable if it does not exist, overrides if it does. -This will force the tests to be run in an isolated process. -This argument can be specified multiple times to provide multiple variables. - -Examples: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - Устанавливает значение переменной среды. -Если переменной среды не существует, она создается. Если переменная среды существует, она переопределяется. -Этот аргумент подразумевает принудительное выполнение тестов в изолированном процессе. -Этот аргумент может быть указан несколько раз для нескольких переменных среды. - -Примеры: --e VARIABLE=abc --e VARIABLE="значение с пробелами" --e VARIABLE="значение;разделенное;точками;с;запятыми" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - - - - NAME="VALUE" - NAME="VALUE" - - The provided project file has an invalid extension: {0}. The provided project file has an invalid extension: {0}. diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.tr.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.tr.xlf index 2f0947f5b3f6..bb1b7f37cd0f 100644 --- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.tr.xlf +++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.tr.xlf @@ -118,36 +118,6 @@ Zaman aşımı davranışı veri tabanlı testlerle birlikte kullanıldığında Defines the path of directory to run. If not specified, it defaults to the current directory. - - Sets the value of an environment variable. -Creates the variable if it does not exist, overrides if it does. -This will force the tests to be run in an isolated process. -This argument can be specified multiple times to provide multiple variables. - -Examples: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - Bir ortam değişkeninin değerini ayarlar. -Değişken yoksa oluşturur, varsa değişkeni geçersiz kılar. -Bu, testleri yalıtılmış bir işlemde çalıştırılmaya zorlar. -Bu bağımsız değişken, birden çok değişken sağlamak için birden çok kez belirtilebilir. - -Örnek: --e DEĞİŞKEN=abc --e DEĞİŞKEN="boşluk içeren değerler" --e DEĞİŞKEN="noktalı virgülle;ayrılmış;değerler" --e DEĞ1=abc -e DEĞ2=def -e DEĞ3=ghi - - - - - NAME="VALUE" - AD="DEĞER" - - The provided project file has an invalid extension: {0}. The provided project file has an invalid extension: {0}. diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.zh-Hans.xlf index 860e119ca0fc..eb07d78e1ba2 100644 --- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.zh-Hans.xlf +++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.zh-Hans.xlf @@ -118,36 +118,6 @@ For MSTest before 2.2.4, the timeout is used for all testcases. Defines the path of directory to run. If not specified, it defaults to the current directory. - - Sets the value of an environment variable. -Creates the variable if it does not exist, overrides if it does. -This will force the tests to be run in an isolated process. -This argument can be specified multiple times to provide multiple variables. - -Examples: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - 设置环境变量的值。 -如果该变量不存在,则创建它;如果它已存在,则替代它。 -这将在隔离的进程中强制运行测试。 -可多次指定此参数来提供多个变量。 - -示例: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - - - - NAME="VALUE" - NAME="VALUE" - - The provided project file has an invalid extension: {0}. The provided project file has an invalid extension: {0}. diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.zh-Hant.xlf index c5553741971d..24bb05a297fc 100644 --- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.zh-Hant.xlf +++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.zh-Hant.xlf @@ -118,36 +118,6 @@ For MSTest before 2.2.4, the timeout is used for all testcases. Defines the path of directory to run. If not specified, it defaults to the current directory. - - Sets the value of an environment variable. -Creates the variable if it does not exist, overrides if it does. -This will force the tests to be run in an isolated process. -This argument can be specified multiple times to provide multiple variables. - -Examples: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - 設定環境變數的值。 -若變數不存在,則加以建立; 若有,則予以覆寫。 -這會強制在隔離流程中執行測試。 -此引數可多次指定,以提供多項變數。 - -範例: --e VARIABLE=abc --e VARIABLE="value with spaces" --e VARIABLE="value;seperated with;semicolons" --e VAR1=abc -e VAR2=def -e VAR3=ghi - - - - - NAME="VALUE" - NAME="VALUE" - - The provided project file has an invalid extension: {0}. The provided project file has an invalid extension: {0}. diff --git a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.cs.xlf b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.cs.xlf index 8735c705a192..40980d8fd9f5 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.cs.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.cs.xlf @@ -51,8 +51,8 @@ The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. This can be done with this command: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org - The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. - This can be done with this command: + Příkaz 'dotnet tool search' bez podmínek přistupuje nuget.org k hledání nástrojů, ale není k dispozici ve vašem nuget.config. Pokud chcete tento příkaz spustit, přidejte ho. + To lze provést pomocí tohoto příkazu: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org Do not translate 'dotnet tool search' or 'nuget.config'. Do not localize the last line at all. diff --git a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.de.xlf b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.de.xlf index e2a2fb2c47e9..bbe92e4a72eb 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.de.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.de.xlf @@ -51,8 +51,8 @@ The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. This can be done with this command: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org - The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. - This can be done with this command: + Der Befehl "dotnet tool search" greift ohne Bedingungen auf nuget.org zu, um Tools zu finden, ist jedoch in Ihrem nuget.config nicht vorhanden. Fügen Sie ihn hinzu, um diesen Befehl auszuführen. + Dies kann mit diesem Befehl erfolgen: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org Do not translate 'dotnet tool search' or 'nuget.config'. Do not localize the last line at all. diff --git a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.es.xlf b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.es.xlf index 8912b64e886e..a356d37d1703 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.es.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.es.xlf @@ -51,8 +51,8 @@ The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. This can be done with this command: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org - The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. - This can be done with this command: + El comando "dotnet tool search" accede incondicionalmente a nuget.org para buscar herramientas, pero no está presente en el nuget.config. Agréguelo para ejecutar este comando. + Esto se puede hacer con este comando: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org Do not translate 'dotnet tool search' or 'nuget.config'. Do not localize the last line at all. diff --git a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.fr.xlf b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.fr.xlf index adf9625fdc88..16f3f3f946a5 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.fr.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.fr.xlf @@ -51,8 +51,8 @@ The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. This can be done with this command: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org - The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. - This can be done with this command: + La commande « dotnet tool search » accède de manière inconditionnelle nuget.org à la recherche d’outils, mais elle n’est pas présente dans votre nuget.config. Ajoutez-le pour exécuter cette commande. + Cette opération peut être effectuée avec cette commande : dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org Do not translate 'dotnet tool search' or 'nuget.config'. Do not localize the last line at all. diff --git a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.it.xlf b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.it.xlf index ca389bb04a5b..11dbc2daa672 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.it.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.it.xlf @@ -51,8 +51,8 @@ The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. This can be done with this command: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org - The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. - This can be done with this command: + Il comando 'dotnet tool search' accede in modo incondizionato nuget.org per trovare strumenti, ma non è presente nel nuget.config. Aggiungerlo per eseguire questo comando. + Questa operazione può essere eseguita con questo comando: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org Do not translate 'dotnet tool search' or 'nuget.config'. Do not localize the last line at all. diff --git a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.ja.xlf b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.ja.xlf index 59c7f632178f..0dc0d4f8e5e8 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.ja.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.ja.xlf @@ -51,8 +51,8 @@ The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. This can be done with this command: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org - The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. - This can be done with this command: + 'dotnet tool search' コマンドは、nuget.org に無条件でアクセスしてツールを検索しますが、nuget.config には存在しません。このコマンドを実行するには、追加してください。 + これは、次のコマンドで実行できます: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org Do not translate 'dotnet tool search' or 'nuget.config'. Do not localize the last line at all. diff --git a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.ko.xlf b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.ko.xlf index e3f997df3bd3..6985c4ce628f 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.ko.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.ko.xlf @@ -51,9 +51,9 @@ The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. This can be done with this command: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org - The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. - This can be done with this command: - dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org + 'dotnet tool search' 명령은 도구를 찾기 위해 nuget.org 무조건 액세스하지만 nuget.config 없습니다. 이 명령을 실행하려면 추가하세요. + 이 명령은 다음 명령을 사용하여 수행할 수 있습니다. + dotnet nuget 소스 추가 https://api.nuget.org/v3/index.json -n nuget.org Do not translate 'dotnet tool search' or 'nuget.config'. Do not localize the last line at all. diff --git a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.pl.xlf b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.pl.xlf index 87564f82fde7..e0a3b1b985a8 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.pl.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.pl.xlf @@ -51,8 +51,8 @@ The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. This can be done with this command: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org - The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. - This can be done with this command: + Polecenie "dotnet tool search" bezwarunkowo uzyskuje dostęp do nuget.org w celu znalezienia narzędzi, ale nie występuje w nuget.config. Dodaj go, aby uruchomić to polecenie. + Można to zrobić za pomocą tego polecenia: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org Do not translate 'dotnet tool search' or 'nuget.config'. Do not localize the last line at all. diff --git a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.pt-BR.xlf index 2367aeb40b37..a33000d9851f 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.pt-BR.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.pt-BR.xlf @@ -51,8 +51,8 @@ The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. This can be done with this command: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org - The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. - This can be done with this command: + O comando 'dotnet tool search' acessa incondicionalmente nuget.org para localizar ferramentas, mas não está presente em seu nuget.config. Adicione-o para executar este comando. + Isso pode ser feito com este comando: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org Do not translate 'dotnet tool search' or 'nuget.config'. Do not localize the last line at all. diff --git a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.ru.xlf b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.ru.xlf index 1cb904fa5f8c..913234dfe843 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.ru.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.ru.xlf @@ -51,8 +51,8 @@ The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. This can be done with this command: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org - The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. - This can be done with this command: + Команда "dotnet tool search" безусловно nuget.org для поиска инструментов, но отсутствует в nuget.config. Добавьте его для выполнения этой команды. + Это можно сделать с помощью этой команды: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org Do not translate 'dotnet tool search' or 'nuget.config'. Do not localize the last line at all. diff --git a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.tr.xlf b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.tr.xlf index fca2bd8d4de3..aaa0f3f83887 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.tr.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.tr.xlf @@ -51,8 +51,8 @@ The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. This can be done with this command: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org - The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. - This can be done with this command: + 'dotnet tool search' komutu koşulsuz olarak nuget.org araçları bulmak için bu komuta erişer, ancak bu komut nuget.config. Bu komutu çalıştırmak için ekleyin. + Bu, şu komutla kullanılabilir: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org Do not translate 'dotnet tool search' or 'nuget.config'. Do not localize the last line at all. diff --git a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.zh-Hans.xlf index bf04ef763834..7a123c60a16e 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.zh-Hans.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.zh-Hans.xlf @@ -51,9 +51,9 @@ The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. This can be done with this command: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org - The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. - This can be done with this command: - dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org + “dotnet 工具搜索”命令无条件访问 nuget.org 以查找工具,但 nuget.config 中不存在该命令。添加它以运行此命令。 + 可以使用此命令完成此操作: + dotnet nuget 添加源 https://api.nuget.org/v3/index.json -n nuget.org Do not translate 'dotnet tool search' or 'nuget.config'. Do not localize the last line at all. diff --git a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.zh-Hant.xlf index 9fda02783409..45277714d064 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.zh-Hant.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/search/xlf/LocalizableStrings.zh-Hant.xlf @@ -51,8 +51,8 @@ The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. This can be done with this command: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org - The 'dotnet tool search' command unconditionally accesses nuget.org to find tools, but it is not present in your nuget.config. Add it to run this command. - This can be done with this command: + 「dotnet 工具搜尋」命令無條件存取 nuget.org 以尋找工具,但該命令不存在於您的 nuget.config 中。新增它以執行此命令。 + 這可以使用此指令來完成: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org Do not translate 'dotnet tool search' or 'nuget.config'. Do not localize the last line at all. diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/IInstaller.cs b/src/Cli/dotnet/commands/dotnet-workload/install/IInstaller.cs index 7267a5492bc5..8dfaa13357c7 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/IInstaller.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/install/IInstaller.cs @@ -14,6 +14,8 @@ internal interface IInstaller : IWorkloadManifestInstaller { int ExitCode { get; } + WorkloadSet GetWorkloadSetContents(string workloadVersion); + void InstallWorkloads(IEnumerable workloadIds, SdkFeatureBand sdkFeatureBand, ITransactionContext transactionContext, DirectoryPath? offlineCache = null); void RepairWorkloads(IEnumerable workloadIds, SdkFeatureBand sdkFeatureBand, DirectoryPath? offlineCache = null); diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/LocalizableStrings.resx b/src/Cli/dotnet/commands/dotnet-workload/install/LocalizableStrings.resx index cd04c02ff902..42c3799c85ee 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/LocalizableStrings.resx +++ b/src/Cli/dotnet/commands/dotnet-workload/install/LocalizableStrings.resx @@ -327,7 +327,7 @@ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}. - "workloadVersion" and "global.json" are literal values and should not be translated. + {Locked="workloadVersion"} Locked={"global.json"} Skip signature verification of workload packages and installers. @@ -348,7 +348,7 @@ Manifest MSI not found in NuGet package {0} - Update to the specified workload version. + A workload version to display or one or more workloads and their versions joined by the '@' character. Installing workload version {0}. @@ -365,4 +365,8 @@ Failed to install workload version {0}: {1} + + Cannot specify a workload version using the --version option while also specifying versions to install using workload@version syntax. + {Locked="--version"} + diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkMsiInstallerClient.cs b/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkMsiInstallerClient.cs index a9acfa057fee..2f26860f62b0 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkMsiInstallerClient.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkMsiInstallerClient.cs @@ -1183,5 +1183,10 @@ void IInstaller.UpdateInstallMode(SdkFeatureBand sdkFeatureBand, bool? newMode) string newModeString = newMode == null ? "" : newMode.Value ? WorkloadConfigCommandParser.UpdateMode_WorkloadSet : WorkloadConfigCommandParser.UpdateMode_Manifests; Reporter.WriteLine(string.Format(LocalizableStrings.UpdatedWorkloadMode, newModeString)); } + + // This method should never be called for this kind of installer. It is challenging to get this information from an MSI + // and totally unnecessary as the information is identical from a file-based installer. It was added to IInstaller only + // to facilitate testing. As a consequence, it does not need to be implemented. + public WorkloadSet GetWorkloadSetContents(string workloadVersion) => throw new NotImplementedException(); } } diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs index 3f3e984d6eac..61b707bf36a3 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs @@ -11,8 +11,6 @@ using Microsoft.NET.Sdk.WorkloadManifestReader; using NuGet.Common; using NuGet.Versioning; -using static Microsoft.NET.Sdk.WorkloadManifestReader.WorkloadResolver; -using System.Text; namespace Microsoft.DotNet.Workloads.Workload.Install { @@ -39,7 +37,22 @@ public WorkloadInstallCommand( tempDirPath: tempDirPath) { _skipManifestUpdate = skipWorkloadManifestUpdate ?? parseResult.GetValue(WorkloadInstallCommandParser.SkipManifestUpdateOption); - _workloadIds = workloadIds ?? parseResult.GetValue(WorkloadInstallCommandParser.WorkloadIdArgument).ToList().AsReadOnly(); + var unprocessedWorkloadIds = workloadIds ?? parseResult.GetValue(WorkloadInstallCommandParser.WorkloadIdArgument); + if (unprocessedWorkloadIds?.Any(id => id.Contains('@')) == true) + { + _workloadIds = unprocessedWorkloadIds.Select(id => id.Split('@')[0]).ToList().AsReadOnly(); + if (SpecifiedWorkloadSetVersionOnCommandLine) + { + throw new GracefulException(LocalizableStrings.CannotSpecifyVersionAndWorkloadIdsByComponent, isUserError: true); + } + + _workloadSetVersionFromCommandLine = unprocessedWorkloadIds; + } + else + { + _workloadIds = unprocessedWorkloadIds.ToList().AsReadOnly(); + } + var resolvedReporter = _printDownloadLinkOnly ? NullReporter.Instance : Reporter; _workloadInstaller = _workloadInstallerFromConstructor ?? diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.cs.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.cs.xlf index f30fd75f4019..6865ac80971d 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.cs.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.cs.xlf @@ -27,6 +27,11 @@ Možnosti {0} a {1} nelze použít společně. Jednu z možností odeberte. + + Cannot specify a workload version using the --version option while also specifying versions to install using workload@version syntax. + Verzi úlohy nejde zadat pomocí možnosti --version a zároveň zadat verze, které se mají nainstalovat, pomocí syntaxe workload@version. + {Locked="--version"} + Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update." Na příkazovém řádku nelze pomocí možnosti --version nebo --from-history zadat konkrétní verzi úlohy, pokud je již verze zadána v souboru global.json {0}. Pokud chcete aktualizovat globálně nainstalovanou verzi úlohy, spusťte příkaz mimo cestu obsahující daný soubor global.json nebo aktualizujte verzi uvedenou v souboru global.json a spusťte příkaz dotnet workload update. @@ -35,7 +40,7 @@ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}. Možnost {0} se nedá použít, pokud je v global.json zadaná verze úlohy. Odeberte možnost {0} nebo odeberte element workloadVersion z {1}. - "workloadVersion" and "global.json" are literal values and should not be translated. + {Locked="workloadVersion"} Locked={"global.json"} Checking for updated workload version. @@ -393,8 +398,8 @@ - Update to the specified workload version. - Aktualizuje verzi na zadanou verzi úlohy. + A workload version to display or one or more workloads and their versions joined by the '@' character. + Verze úlohy, která se má zobrazit, nebo jedna nebo více úloh a jejich verzí připojených znakem @ diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.de.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.de.xlf index f6fae7626734..be03107879fc 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.de.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.de.xlf @@ -27,6 +27,11 @@ Die Optionen {0} und {1} können nicht zusammen verwendet werden. Entfernen Sie eine der Optionen. + + Cannot specify a workload version using the --version option while also specifying versions to install using workload@version syntax. + Es kann keine Workloadversion mithilfe der Option --version angegeben werden, es können jedoch auch Versionen angegeben werden, die mithilfe workload@version Syntax installiert werden sollen. + {Locked="--version"} + Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update." Eine bestimmte Workload-Version kann in der Befehlszeile nicht über „--version“ oder „--from-history“ angegeben werden, wenn bereits eine Version in der global.json-Datei „{0}“ angegeben ist. Um die global installierte Workload-Version zu aktualisieren, führen Sie den Befehl außerhalb des Pfads aus, der diese global.json-Datei enthält, oder aktualisieren Sie die in der global.json Datei angegebene Version, und führen Sie „dotnet workload update“ aus. @@ -34,8 +39,8 @@ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}. - Die Option {0} kann nicht verwendet werden, wenn die Workloadversion in global.json angegeben ist. Entfernen Sie die Option {0}, oder entfernen Sie das WorkloadVersion-Element aus {1}. - "workloadVersion" and "global.json" are literal values and should not be translated. + Die Option {0} kann nicht verwendet werden, wenn die workloadVersion in global.json angegeben ist. Entfernen Sie die Option {0}, oder entfernen Sie das workloadVersion-Element aus {1}. + {Locked="workloadVersion"} Locked={"global.json"} Checking for updated workload version. @@ -393,8 +398,8 @@ - Update to the specified workload version. - Aktualisieren Sie auf die angegebene Workloadversion. + A workload version to display or one or more workloads and their versions joined by the '@' character. + Eine Workloadversion zum Anzeigen oder mindestens eine Workload und deren Versionen, die mit dem Zeichen "@" verknüpft sind. diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.es.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.es.xlf index 65251c1545d6..347522e64aa2 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.es.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.es.xlf @@ -27,6 +27,11 @@ No se pueden usar las opciones {0} y {1} juntas. Quite una de las opciones. + + Cannot specify a workload version using the --version option while also specifying versions to install using workload@version syntax. + No se puede especificar una versión de carga de trabajo con la opción --version y especificar también las versiones que se van a instalar con la sintaxis workload@version. + {Locked="--version"} + Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update." No se puede especificar una versión de carga de trabajo determinada en la línea de comandos mediante --version o --from-history cuando ya hay una versión especificada en el archivo global.json {0}. Para actualizar la versión de carga de trabajo instalada globalmente, ejecute el comando fuera de la ruta de acceso que contiene ese archivo global.json o actualice la versión especificada en el archivo global.json y ejecute "dotnet workload update". @@ -35,7 +40,7 @@ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}. No se puede usar la opción {0} cuando se especifica la versión de la carga de trabajo en global.json. Quite la opción {0} o quite el elemento "workloadVersion" de {1}. - "workloadVersion" and "global.json" are literal values and should not be translated. + {Locked="workloadVersion"} Locked={"global.json"} Checking for updated workload version. @@ -393,8 +398,8 @@ - Update to the specified workload version. - Actualice a la versión de carga de trabajo especificada. + A workload version to display or one or more workloads and their versions joined by the '@' character. + Una versión de carga de trabajo para mostrar o una o más cargas de trabajo y sus versiones unidas por el carácter "@". diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.fr.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.fr.xlf index be7157ed7cf8..fee46cc522fa 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.fr.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.fr.xlf @@ -27,6 +27,11 @@ Impossible d’utiliser les options {0} et {1} ensemble. Supprimez l’une des options. + + Cannot specify a workload version using the --version option while also specifying versions to install using workload@version syntax. + Impossible de spécifier une version de charge de travail à l’aide de l’option --version tout en spécifiant également les versions à installer à l’aide de la syntaxe workload@version. + {Locked="--version"} + Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update." Impossible de spécifier une version de charge de travail particulière sur la ligne de commande via --version ou --from-history lorsqu’une version est déjà spécifiée dans global.json fichier {0}. Pour mettre à jour la version de la charge de travail installée globalement, exécutez la commande en dehors du chemin contenant ce fichier global.json ou mettez à jour la version spécifiée dans le fichier global.json et exécutez « dotnet workload update » @@ -35,7 +40,7 @@ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}. Impossible d’utiliser l’option {0} lorsque la version de la charge de travail est spécifiée dans global.json. Supprimez l’option {0} ou supprimez l’élément « workloadVersion » de {1}. - "workloadVersion" and "global.json" are literal values and should not be translated. + {Locked="workloadVersion"} Locked={"global.json"} Checking for updated workload version. @@ -393,8 +398,8 @@ - Update to the specified workload version. - Mettre à jour vers la version de charge de travail spécifiée. + A workload version to display or one or more workloads and their versions joined by the '@' character. + Version de charge de travail à afficher ou une ou plusieurs charges de travail et leurs versions jointes par le caractère « @ ». diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.it.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.it.xlf index 037c31d480a2..1a5d0a4f63eb 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.it.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.it.xlf @@ -27,6 +27,11 @@ Impossibile utilizzare contemporaneamente le opzioni {0} e {1}. Rimuove una delle opzioni. + + Cannot specify a workload version using the --version option while also specifying versions to install using workload@version syntax. + Non è possibile specificare una versione del carico di lavoro usando l'opzione --version specificando anche le versioni da installare con workload@version sintassi. + {Locked="--version"} + Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update." Impossibile specificare una determinata versione del carico di lavoro nella riga di comando tramite --version o --from-history quando è già specificata una versione nel file global.json {0}. Per aggiornare la versione del carico di lavoro installata a livello globale, eseguire il comando all'esterno del percorso contenente tale file global.json o aggiornare la versione specificata nel file di global.json ed eseguire "dotnet workload update". @@ -35,7 +40,7 @@ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}. Non è possibile usare l'opzione {0} quando la versione del carico di lavoro è specificata in global.json. Rimuovere l'opzione {0} o rimuovere l'elemento 'workloadVersion' da {1}. - "workloadVersion" and "global.json" are literal values and should not be translated. + {Locked="workloadVersion"} Locked={"global.json"} Checking for updated workload version. @@ -393,8 +398,8 @@ - Update to the specified workload version. - Eseguire l'aggiornamento alla versione del carico di lavoro specificata. + A workload version to display or one or more workloads and their versions joined by the '@' character. + Versione del carico di lavoro da visualizzare o da uno o più carichi di lavoro e relative versioni aggiunte dal carattere '@'. diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ja.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ja.xlf index a0c30d7676b7..9b77158b059f 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ja.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ja.xlf @@ -27,6 +27,11 @@ {0} オプションと {1} オプションを同時に使用することはできません。いずれかのオプションを削除してください。 + + Cannot specify a workload version using the --version option while also specifying versions to install using workload@version syntax. + --version オプションを使用してワークロードのバージョンを指定する一方で、workload@version構文を使用してインストールするバージョンを指定することはできません。 + {Locked="--version"} + Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update." global.json ファイル {0} に既にバージョンが指定されている場合は、コマンド ラインで --version または --from-history を使用して特定のワークロード バージョンを指定することはできません。グローバルにインストールされたワークロード バージョンを更新するには、その global.json ファイルを含むパスの外部でコマンドを実行するか、global.json ファイルで指定されたバージョンを更新して、"dotnet workload update" を実行します。 @@ -35,7 +40,7 @@ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}. ワークロードのバージョンが global.json で指定されている場合、{0} オプションは使用できません。{0} オプションを削除するか、{1} から 'workloadVersion' 要素を削除してください。 - "workloadVersion" and "global.json" are literal values and should not be translated. + {Locked="workloadVersion"} Locked={"global.json"} Checking for updated workload version. @@ -393,8 +398,8 @@ - Update to the specified workload version. - 指定されたワークロード バージョンに更新します。 + A workload version to display or one or more workloads and their versions joined by the '@' character. + 表示するワークロードのバージョン、または '@' 文字で結合された 1 つ以上のワークロードとそのバージョン。 diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ko.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ko.xlf index 35c637fc89c6..afc4c6730e4c 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ko.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ko.xlf @@ -27,6 +27,11 @@ {0} 및 {1} 옵션을 함께 사용할 수 없습니다. 옵션 중 하나를 제거하세요. + + Cannot specify a workload version using the --version option while also specifying versions to install using workload@version syntax. + workload@version 구문을 사용하여 설치할 버전도 지정하면서 --version 옵션을 사용하여 작업 버전을 지정할 수 없습니다. + {Locked="--version"} + Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update." global.json 파일 {0}에 지정된 버전이 이미 있는 경우 --version 또는 --from-history를 통해 명령줄에서 특정 워크로드 버전을 지정할 수 없습니다. 전역으로 설치된 워크로드 버전을 업데이트하려면 해당 global.json 파일이 포함된 경로 외부에서 명령을 실행하거나 global.json 파일에 지정된 버전을 업데이트하고 "dotnet 워크로드 업데이트"를 실행합니다. @@ -35,7 +40,7 @@ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}. global.json에 워크로드 버전이 지정된 경우 {0} 옵션을 사용할 수 없습니다. {0} 옵션을 제거하거나, {1}에서 'workloadVersion' 요소를 제거하세요. - "workloadVersion" and "global.json" are literal values and should not be translated. + {Locked="workloadVersion"} Locked={"global.json"} Checking for updated workload version. @@ -393,8 +398,8 @@ - Update to the specified workload version. - 지정된 워크로드 버전으로 업데이트합니다. + A workload version to display or one or more workloads and their versions joined by the '@' character. + 표시할 워크로드 버전 또는 하나 이상의 워크로드 및 해당 버전이 '@' 문자로 결합되었습니다. diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.pl.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.pl.xlf index 6c5f1cae1360..a4400738fd41 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.pl.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.pl.xlf @@ -27,6 +27,11 @@ Nie można używać opcji {0} i {1} razem. Usuń jedną z opcji. + + Cannot specify a workload version using the --version option while also specifying versions to install using workload@version syntax. + Nie można określić wersji obciążenia przy użyciu opcji --version, określając jednocześnie wersje do zainstalowania przy użyciu składni workload@version. + {Locked="--version"} + Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update." Nie można określić określonej wersji obciążenia w wierszu polecenia za pomocą opcji --version lub --from-history, jeśli istnieje już wersja określona w pliku global.json {0}. Aby zaktualizować wersję obciążenia zainstalowaną globalnie, uruchom polecenie poza ścieżką zawierającą ten plik global.json lub zaktualizuj wersję określoną w pliku global.json i uruchom polecenie „dotnet workload update”. @@ -35,7 +40,7 @@ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}. Nie można użyć opcji {0}, jeśli wersja obciążenia jest określona w pliku global.json. Usuń opcję {0} lub usuń element „workloadVersion” z {1}. - "workloadVersion" and "global.json" are literal values and should not be translated. + {Locked="workloadVersion"} Locked={"global.json"} Checking for updated workload version. @@ -393,8 +398,8 @@ - Update to the specified workload version. - Zaktualizuj do określonej wersji obciążenia. + A workload version to display or one or more workloads and their versions joined by the '@' character. + Wersja obciążenia do wyświetlenia lub co najmniej jednego obciążenia i ich wersji dołączonych za pomocą znaku "@". diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.pt-BR.xlf index 2f0f51b1011c..1f1f7157d4b2 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.pt-BR.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.pt-BR.xlf @@ -27,6 +27,11 @@ Não é possível usar as opções {0} e {1} juntas. Escolha uma das opções. + + Cannot specify a workload version using the --version option while also specifying versions to install using workload@version syntax. + Não é possível especificar uma versão de carga de trabalho usando --version opção ao especificar também as versões a serem instaladas usando workload@version sintaxe. + {Locked="--version"} + Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update." Não é possível especificar uma versão específica da carga de trabalho na linha de comando por meio de --version ou --from-history quando já existe uma versão especificada no arquivo global.json {0}. Para atualizar a versão da carga de trabalho instalada globalmente, execute o comando fora do caminho que contém o arquivo global.json ou atualize a versão especificada no arquivo global.json e execute "dotnet workload update". @@ -35,7 +40,7 @@ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}. Não é possível usar a opção {0} quando a versão da carga de trabalho é especificada em global.json. Remova a opção {0} ou remova o elemento 'workloadVersion' de {1}. - "workloadVersion" and "global.json" are literal values and should not be translated. + {Locked="workloadVersion"} Locked={"global.json"} Checking for updated workload version. @@ -393,8 +398,8 @@ - Update to the specified workload version. - Atualize para a versão de carga de trabalho especificada. + A workload version to display or one or more workloads and their versions joined by the '@' character. + Uma versão de carga de trabalho a ser exibida ou uma ou mais cargas de trabalho e suas versões ingressadas pelo caractere '@'. diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ru.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ru.xlf index 86708c461815..b7470731454e 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ru.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ru.xlf @@ -27,6 +27,11 @@ Невозможно использовать параметры {0} и {1} одновременно. Удалите один из параметров. + + Cannot specify a workload version using the --version option while also specifying versions to install using workload@version syntax. + Невозможно указать версию рабочей нагрузки с помощью параметра --version при указании версий для установки с workload@version синтаксиса. + {Locked="--version"} + Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update." Невозможно указать конкретную версию рабочей нагрузки в командной строке с помощью --version или --from-history, если в файле global.json уже указана версия {0}. Чтобы обновить глобально установленную версию рабочей нагрузки, выполните команду вне пути, содержащего этот файл global.json, либо измените версию в файле global.json и выполните команду "dotnet workload update". @@ -35,7 +40,7 @@ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}. Невозможно использовать параметр {0}, если версия рабочей нагрузки указана в файле global.json. Удалите параметр {0} или удалите элемент "workloadVersion" из {1}. - "workloadVersion" and "global.json" are literal values and should not be translated. + {Locked="workloadVersion"} Locked={"global.json"} Checking for updated workload version. @@ -393,8 +398,8 @@ - Update to the specified workload version. - Обновление до указанной версии рабочей нагрузки. + A workload version to display or one or more workloads and their versions joined by the '@' character. + Версия рабочей нагрузки для отображения или одна или несколько рабочих нагрузок и их версий, присоединенных символом "@". diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.tr.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.tr.xlf index bc36b4debfa5..44be8dc036e7 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.tr.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.tr.xlf @@ -27,6 +27,11 @@ {0} ve {1} seçenekleri birlikte kullanılamaz. Seçeneklerden birini kaldırın. + + Cannot specify a workload version using the --version option while also specifying versions to install using workload@version syntax. + İş yükü sürümü, --version kullanılarak yüklenecek sürümler de belirtilirken workload@version belirtilemez. + {Locked="--version"} + Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update." {0} global.json dosyasında zaten belirtilen bir sürüm varsa, “--version” veya “--from-history” aracılığıyla komut satırında belirli bir iş yükü sürümü belirtilemez. Genel olarak yüklenen iş yükü sürümünü güncelleştirmek için, komutu global.json dosyasını içeren yolun dışında çalıştırın veya global.json dosyasında belirtilen sürümü güncelleştirin ve “dotnet workload update” komutunu çalıştırın. @@ -35,7 +40,7 @@ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}. Global.json'da iş yükü sürümü belirtildiğinde {0} seçeneği kullanılamaz. {0} seçeneğini kaldırın veya "workloadVersion" öğesini {1}‘den kaldırın. - "workloadVersion" and "global.json" are literal values and should not be translated. + {Locked="workloadVersion"} Locked={"global.json"} Checking for updated workload version. @@ -393,8 +398,8 @@ - Update to the specified workload version. - Belirtilen iş yükü sürümünde güncelleştirme var. + A workload version to display or one or more workloads and their versions joined by the '@' character. + Görüntülenecek iş yükü sürümü veya bir veya daha fazla iş yükü ve '@' karakteriyle birleştirilmiş sürümleri. diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.zh-Hans.xlf index deb2a9a86c41..37bd4d6583df 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.zh-Hans.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.zh-Hans.xlf @@ -27,6 +27,11 @@ 不能同时使用 {0} 和 {1} 选项。移除其中一个选项。 + + Cannot specify a workload version using the --version option while also specifying versions to install using workload@version syntax. + 在指定要使用workload@version语法安装的版本时,不能使用 --version 选项指定工作负载版本。 + {Locked="--version"} + Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update." 当 global.json 文件 {0} 中已指定版本时,无法在命令行上通过 --version 或 --from-history 指定特定工作负载版本。若要更新全局安装的工作负载版本,请在包含该 global.json 文件的路径外部运行命令,或者更新 global.json 文件中指定的版本,然后运行 "dotnet workload update"。 @@ -35,7 +40,7 @@ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}. 在 global.json 中指定工作负载版本时,无法使用 {0} 选项。移除 {0} 选项,或从 {1} 中移除“workloadVersion”元素。 - "workloadVersion" and "global.json" are literal values and should not be translated. + {Locked="workloadVersion"} Locked={"global.json"} Checking for updated workload version. @@ -393,8 +398,8 @@ - Update to the specified workload version. - 更新到指定的工作负载版本。 + A workload version to display or one or more workloads and their versions joined by the '@' character. + 要显示的工作负载版本或一个或多个工作负载及其版本由 “@” 字符联接。 diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.zh-Hant.xlf index a0af290f566c..f589e4de7e1c 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.zh-Hant.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.zh-Hant.xlf @@ -27,6 +27,11 @@ 無法同時使用 {0} 與 {1} 選項。移除其中一個選項。 + + Cannot specify a workload version using the --version option while also specifying versions to install using workload@version syntax. + 同時指定要使用workload@version語法安裝的版本時,無法使用 --version 選項指定工作負載版本。 + {Locked="--version"} + Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update." 當 global.json 檔案 {0} 中已指定版本時,無法在命令列上透過 --version 或 --from-history 指定特定工作負載版本。若要更新全域安裝的工作負載版本,請在包含該 global.json 檔案的路徑外執行命令,或更新 global.json 檔案中指定的版本,然後執行 "dotnet workload update"。 @@ -35,7 +40,7 @@ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}. global.json 中指定工作負載版本時,無法使用 {0} 選項。移除 {0} 選項,或從 {1} 移除 'workloadVersion' 元素。 - "workloadVersion" and "global.json" are literal values and should not be translated. + {Locked="workloadVersion"} Locked={"global.json"} Checking for updated workload version. @@ -393,8 +398,8 @@ - Update to the specified workload version. - 更新至指定的工作負載版本。 + A workload version to display or one or more workloads and their versions joined by the '@' character. + 要顯示的工作負載版本,或是一或多個工作負載及其由 '@' 字元加入的版本。 diff --git a/src/Cli/dotnet/commands/dotnet-workload/restore/WorkloadRestoreCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/restore/WorkloadRestoreCommand.cs index 41fa1049bf3b..f25690d52963 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/restore/WorkloadRestoreCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/restore/WorkloadRestoreCommand.cs @@ -8,6 +8,7 @@ using Microsoft.DotNet.Cli; using Microsoft.DotNet.Cli.NuGetPackageDownloader; using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Tools.Common; using Microsoft.DotNet.Workloads.Workload.Install; using Microsoft.DotNet.Workloads.Workload.Update; using Microsoft.Extensions.EnvironmentAbstractions; @@ -122,13 +123,13 @@ internal static List DiscoverAllProjects(string currentDirectory, var projectFiles = new List(); if (slnOrProjectArgument == null || !slnOrProjectArgument.Any()) { - slnFiles = Directory.GetFiles(currentDirectory, "*.sln").ToList(); + slnFiles = SlnFileFactory.ListSolutionFilesInDirectory(currentDirectory, false).ToList(); projectFiles.AddRange(Directory.GetFiles(currentDirectory, "*.*proj")); } else { slnFiles = slnOrProjectArgument - .Where(s => Path.GetExtension(s).Equals(".sln", StringComparison.OrdinalIgnoreCase)) + .Where(s => Path.GetExtension(s).Equals(".sln", StringComparison.OrdinalIgnoreCase) || Path.GetExtension(s).Equals(".slnx", StringComparison.OrdinalIgnoreCase)) .Select(Path.GetFullPath).ToList(); projectFiles = slnOrProjectArgument .Where(s => Path.GetExtension(s).EndsWith("proj", StringComparison.OrdinalIgnoreCase)) @@ -137,12 +138,8 @@ internal static List DiscoverAllProjects(string currentDirectory, foreach (string file in slnFiles) { - var solutionFile = SolutionFile.Parse(file); - var projects = solutionFile.ProjectsInOrder.Where(p => p.ProjectType != SolutionProjectType.SolutionFolder); - foreach (var p in projects) - { - projectFiles.Add(p.AbsolutePath); - } + var solutionFile = SlnFileFactory.CreateFromFileOrDirectory(file); + projectFiles.AddRange(solutionFile.SolutionProjects.Select(p => p.FilePath)); } if (projectFiles.Count == 0) diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/LocalizableStrings.resx b/src/Cli/dotnet/commands/dotnet-workload/search/LocalizableStrings.resx index cce5241a328e..656a228086ae 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/LocalizableStrings.resx +++ b/src/Cli/dotnet/commands/dotnet-workload/search/LocalizableStrings.resx @@ -136,8 +136,37 @@ Platforms - Output a list of the latest released workload versions. Takes the --take option to specify how many to provide and --format to alter the format. - Do not localize --take or --format + 'dotnet workload search version' has three functions depending on its argument: + 1. If no argument is specified, it outputs a list of the latest released workload versions from this feature band. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. If a workload version is provided as an argument, it outputs a table of various workloads and their versions for the specified workload version. Takes the --format option to alter the output format. + Example: + dotnet workload search version 9.0.201 + Workload manifest ID Manifest feature band Manifest Version + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. If one or more workloads are provided along with their versions (by joining them with the '@' character), it outputs workload versions that match the provided versions. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + {Locked="--take"} {Locked="--format"} {Locked="dotnet workload search version"} {Locked="workloadVersion"} Changes the format of outputted workload versions. Can take 'json' or 'list' @@ -163,5 +192,8 @@ Manifest feature band + + No workload version matching {0} was found. + diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchVersionsCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchVersionsCommand.cs index 64e14d4fc4d1..82c308f7cae2 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchVersionsCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchVersionsCommand.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.CommandLine; using System.Text.Json; using Microsoft.Deployment.DotNet.Releases; @@ -9,11 +8,9 @@ using Microsoft.DotNet.Cli.NuGetPackageDownloader; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Configurer; -using Microsoft.DotNet.ToolPackage; using Microsoft.DotNet.Workloads.Workload.Install; using Microsoft.NET.Sdk.WorkloadManifestReader; using Microsoft.TemplateEngine.Cli.Commands; -using NuGet.Versioning; using InformationStrings = Microsoft.DotNet.Workloads.Workload.LocalizableStrings; @@ -24,16 +21,21 @@ internal class WorkloadSearchVersionsCommand : WorkloadCommandBase private readonly ReleaseVersion _sdkVersion; private readonly int _numberOfWorkloadSetsToTake; private readonly string _workloadSetOutputFormat; - private readonly FileBasedInstaller _installer; - private readonly string _workloadVersion; + private readonly IInstaller _installer; + private readonly IEnumerable _workloadVersion; private readonly bool _includePreviews; + private readonly IWorkloadResolver _resolver; public WorkloadSearchVersionsCommand( ParseResult result, IReporter reporter = null, - IWorkloadResolverFactory workloadResolverFactory = null) : base(result, CommonOptions.HiddenVerbosityOption, reporter) + IWorkloadResolverFactory workloadResolverFactory = null, + IInstaller installer = null, + INuGetPackageDownloader nugetPackageDownloader = null, + IWorkloadResolver resolver = null, + ReleaseVersion sdkVersion = null) : base(result, CommonOptions.HiddenVerbosityOption, reporter, nugetPackageDownloader: nugetPackageDownloader) { - workloadResolverFactory = workloadResolverFactory ?? new WorkloadResolverFactory(); + workloadResolverFactory ??= new WorkloadResolverFactory(); if (!string.IsNullOrEmpty(result.GetValue(WorkloadSearchCommandParser.VersionOption))) { @@ -42,56 +44,81 @@ public WorkloadSearchVersionsCommand( var creationResult = workloadResolverFactory.Create(); - _sdkVersion = creationResult.SdkVersion; - var workloadResolver = creationResult.WorkloadResolver; + _sdkVersion = sdkVersion ?? creationResult.SdkVersion; + _resolver = resolver ?? creationResult.WorkloadResolver; _numberOfWorkloadSetsToTake = result.GetValue(WorkloadSearchVersionsCommandParser.TakeOption); _workloadSetOutputFormat = result.GetValue(WorkloadSearchVersionsCommandParser.FormatOption); // For these operations, we don't have to respect 'msi' because they're equivalent between the two workload // install types, and FileBased is much easier to work with. - _installer = new FileBasedInstaller( + _installer = installer ?? GenerateInstaller(Reporter, new SdkFeatureBand(_sdkVersion), _resolver, Verbosity, result.HasOption(SharedOptions.InteractiveOption)); + + _workloadVersion = result.GetValue(WorkloadSearchVersionsCommandParser.WorkloadVersionArgument); + + _includePreviews = result.HasOption(WorkloadSearchVersionsCommandParser.IncludePreviewsOption) ? + result.GetValue(WorkloadSearchVersionsCommandParser.IncludePreviewsOption) : + new SdkFeatureBand(_sdkVersion).IsPrerelease; + + } + + private static IInstaller GenerateInstaller(IReporter reporter, SdkFeatureBand sdkFeatureBand, IWorkloadResolver workloadResolver, VerbosityOptions verbosity, bool interactive) + { + return new FileBasedInstaller( reporter, - new SdkFeatureBand(_sdkVersion), + sdkFeatureBand, workloadResolver, CliFolderPathCalculator.DotnetUserProfileFolderPath, nugetPackageDownloader: null, dotnetDir: Path.GetDirectoryName(Environment.ProcessPath), tempDirPath: null, - verbosity: Verbosity, + verbosity: verbosity, packageSourceLocation: null, - restoreActionConfig: new RestoreActionConfig(result.HasOption(SharedOptions.InteractiveOption)), + restoreActionConfig: new RestoreActionConfig(interactive), nugetPackageDownloaderVerbosity: VerbosityOptions.quiet ); - - _workloadVersion = result.GetValue(WorkloadSearchVersionsCommandParser.WorkloadVersionArgument); - - _includePreviews = result.HasOption(WorkloadSearchVersionsCommandParser.IncludePreviewsOption) ? - result.GetValue(WorkloadSearchVersionsCommandParser.IncludePreviewsOption) : - new SdkFeatureBand(_sdkVersion).IsPrerelease; } public override int Execute() { - if (_workloadVersion is null) + if (_workloadVersion.Count() == 0) { - var featureBand = new SdkFeatureBand(_sdkVersion); - var packageId = _installer.GetManifestPackageId(new ManifestId("Microsoft.NET.Workloads"), featureBand); - List versions; try { - versions = PackageDownloader.GetLatestPackageVersions(packageId, _numberOfWorkloadSetsToTake, packageSourceLocation: null, includePreview: _includePreviews) - .GetAwaiter().GetResult() - .Select(version => WorkloadSetVersion.FromWorkloadSetPackageVersion(featureBand, version.ToString())) - .ToList(); + versions = GetVersions(_numberOfWorkloadSetsToTake); } catch (NuGetPackageNotFoundException) { - Microsoft.DotNet.Cli.Utils.Reporter.Error.WriteLine(string.Format(LocalizableStrings.NoWorkloadVersionsFound, featureBand)); + Cli.Utils.Reporter.Error.WriteLine(string.Format(LocalizableStrings.NoWorkloadVersionsFound, new SdkFeatureBand(_sdkVersion))); return 0; } + if (_workloadSetOutputFormat?.Equals("json", StringComparison.OrdinalIgnoreCase) == true) + { + Reporter.WriteLine(JsonSerializer.Serialize(versions.Select(version => new Dictionary() + { + { "workloadVersion", version } + }))); + } + else + { + Reporter.WriteLine(string.Join('\n', versions)); + } + } + else if (_workloadVersion.Any(v => v.Contains('@'))) + { + var versions = FindBestWorkloadSetsFromComponents()?.Take(_numberOfWorkloadSetsToTake); + if (versions is null) + { + return 0; + } + + if (!versions.Any()) + { + Reporter.WriteLine(string.Format(LocalizableStrings.WorkloadVersionWithSpecifiedManifestNotFound, string.Join(' ', _workloadVersion))); + } + else if (_workloadSetOutputFormat?.Equals("json", StringComparison.OrdinalIgnoreCase) == true) { Reporter.WriteLine(JsonSerializer.Serialize(versions.Select(version => version.ToDictionary(_ => "workloadVersion", v => v)))); } @@ -102,7 +129,7 @@ public override int Execute() } else { - var workloadSet = _installer.GetWorkloadSetContents(_workloadVersion); + var workloadSet = _installer.GetWorkloadSetContents(_workloadVersion.Single()); if (_workloadSetOutputFormat?.Equals("json", StringComparison.OrdinalIgnoreCase) == true) { var set = new WorkloadSet() { ManifestVersions = workloadSet.ManifestVersions }; @@ -123,5 +150,55 @@ public override int Execute() return 0; } + + private List GetVersions(int numberOfWorkloadSetsToTake) + { + return GetVersions(numberOfWorkloadSetsToTake, new SdkFeatureBand(_sdkVersion), _installer, _includePreviews, PackageDownloader, _resolver); + } + + private static List GetVersions(int numberOfWorkloadSetsToTake, SdkFeatureBand featureBand, IInstaller installer, bool includePreviews, INuGetPackageDownloader packageDownloader, IWorkloadResolver resolver) + { + installer ??= GenerateInstaller(Cli.Utils.Reporter.NullReporter, featureBand, resolver, VerbosityOptions.d, interactive: false); + var packageId = installer.GetManifestPackageId(new ManifestId("Microsoft.NET.Workloads"), featureBand); + + return packageDownloader.GetLatestPackageVersions(packageId, numberOfWorkloadSetsToTake, packageSourceLocation: null, includePreview: includePreviews) + .GetAwaiter().GetResult() + .Select(version => WorkloadSetVersion.FromWorkloadSetPackageVersion(featureBand, version.ToString())) + .ToList(); + } + + private IEnumerable FindBestWorkloadSetsFromComponents() + { + return FindBestWorkloadSetsFromComponents(new SdkFeatureBand(_sdkVersion), _installer, _includePreviews, PackageDownloader, _workloadVersion, _resolver, _numberOfWorkloadSetsToTake); + } + + public static IEnumerable FindBestWorkloadSetsFromComponents(SdkFeatureBand featureBand, IInstaller installer, bool includePreviews, INuGetPackageDownloader packageDownloader, IEnumerable workloadVersions, IWorkloadResolver resolver, int numberOfWorkloadSetsToTake) + { + installer ??= GenerateInstaller(Cli.Utils.Reporter.NullReporter, featureBand, resolver, VerbosityOptions.d, interactive: false); + List versions; + try + { + // 0 indicates 'give all versions'. Not all will match, so we don't know how many we will need + versions = GetVersions(0, featureBand, installer, includePreviews, packageDownloader, resolver); + } + catch (NuGetPackageNotFoundException) + { + Cli.Utils.Reporter.Error.WriteLine(string.Format(LocalizableStrings.NoWorkloadVersionsFound, featureBand)); + return null; + } + + var manifestIdsAndVersions = workloadVersions.Select(version => + { + var split = version.Split('@'); + return (new ManifestId(resolver.GetManifestFromWorkload(new WorkloadId(split[0])).Id), new ManifestVersion(split[1])); + }); + + // Since these are ordered by version (descending), the first is the highest version + return versions.Where(version => + { + var manifestVersions = installer.GetWorkloadSetContents(version).ManifestVersions; + return manifestIdsAndVersions.All(tuple => manifestVersions.ContainsKey(tuple.Item1) && manifestVersions[tuple.Item1].Version.Equals(tuple.Item2)); + }).Take(numberOfWorkloadSetsToTake); + } } } diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchVersionsCommandParser.cs b/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchVersionsCommandParser.cs index b733f0e01a93..90afc267dd85 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchVersionsCommandParser.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchVersionsCommandParser.cs @@ -10,10 +10,10 @@ namespace Microsoft.DotNet.Cli { internal static class WorkloadSearchVersionsCommandParser { - public static readonly CliArgument WorkloadVersionArgument = + public static readonly CliArgument> WorkloadVersionArgument = new(LocalizableStrings.WorkloadVersionArgument) { - Arity = ArgumentArity.ZeroOrOne, + Arity = ArgumentArity.ZeroOrMore, Description = LocalizableStrings.WorkloadVersionArgumentDescription }; @@ -60,9 +60,9 @@ private static CliCommand ConstructCommand() command.Validators.Add(result => { var versionArgument = result.GetValue(WorkloadVersionArgument); - if (versionArgument is not null && !WorkloadSetVersion.IsWorkloadSetPackageVersion(versionArgument)) + if (versionArgument is not null && !versionArgument.All(v => v.Contains('@')) && !WorkloadSetVersion.IsWorkloadSetPackageVersion(versionArgument.SingleOrDefault(defaultValue: string.Empty))) { - result.AddError(string.Format(CommandLineValidation.LocalizableStrings.UnrecognizedCommandOrArgument, versionArgument)); + result.AddError(string.Format(CommandLineValidation.LocalizableStrings.UnrecognizedCommandOrArgument, string.Join(' ', versionArgument))); } }); diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.cs.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.cs.xlf index d4d0e1231331..af9877180d73 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.cs.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.cs.xlf @@ -33,9 +33,67 @@ - Output a list of the latest released workload versions. Takes the --take option to specify how many to provide and --format to alter the format. - Vypsat seznam nejnovějších vydaných verzí úloh. Pomocí možnosti --take určíte, kolik jich má být poskytnuto, a pomocí --format změníte formát. - Do not localize --take or --format + 'dotnet workload search version' has three functions depending on its argument: + 1. If no argument is specified, it outputs a list of the latest released workload versions from this feature band. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. If a workload version is provided as an argument, it outputs a table of various workloads and their versions for the specified workload version. Takes the --format option to alter the output format. + Example: + dotnet workload search version 9.0.201 + Workload manifest ID Manifest feature band Manifest Version + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. If one or more workloads are provided along with their versions (by joining them with the '@' character), it outputs workload versions that match the provided versions. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + 'dotnet workload search version' má v závislosti na argumentu tři funkce: + 1. Pokud se nezadá žádný argument, vypíše se z tohoto pásma funkcí seznam nejnovějších verzí uvolněných úloh. Přijímá možnost --take určující, kolik má být zadáno, a --format změnit formát. + Příklad: + dotnet workload search version --take 2 --format JSON + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. Pokud se jako argument zadá verze úlohy, zobrazí se pro zadanou verzi úlohy tabulka různých úloh a jejich verze. Převezme možnost --format pro změnu výstupního formátu. + Příklad: + dotnet workload search version 9.0.201 + Verze manifestu skupiny funkcí manifestu ID manifestu úlohy + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.mac 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. Pokud je k dispozici nejméně jedna úloha spolu s jejich verzemi (spojením pomocí znaku @), vyjdou výstupy verzí úloh, které odpovídají zadaným verzím. Přebírá možnost --take určující, kolik má být zadáno, a --format změnit formát. + Příklad: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + {Locked="--take"} {Locked="--format"} {Locked="dotnet workload search version"} {Locked="workloadVersion"} The --take option must be positive. @@ -77,6 +135,11 @@ Verze manifestu výstupní úlohy přidružené k zadané verzi úlohy. + + No workload version matching {0} was found. + Nenašla se žádná verze úlohy odpovídající {0}. + + \ No newline at end of file diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.de.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.de.xlf index ff68931ba697..a9644b1f2294 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.de.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.de.xlf @@ -33,9 +33,67 @@ - Output a list of the latest released workload versions. Takes the --take option to specify how many to provide and --format to alter the format. - Geben eine Liste der neuesten veröffentlichten Workloadversionen aus. Verwendet die Option „--take“, um anzugeben, wie viele angegeben werden sollen, und „--format“, um das Format zu ändern. - Do not localize --take or --format + 'dotnet workload search version' has three functions depending on its argument: + 1. If no argument is specified, it outputs a list of the latest released workload versions from this feature band. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. If a workload version is provided as an argument, it outputs a table of various workloads and their versions for the specified workload version. Takes the --format option to alter the output format. + Example: + dotnet workload search version 9.0.201 + Workload manifest ID Manifest feature band Manifest Version + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. If one or more workloads are provided along with their versions (by joining them with the '@' character), it outputs workload versions that match the provided versions. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + 'dotnet workload search version' hat je nach Argument drei Funktionen: + 1. Wenn kein Argument angegeben wird, wird eine Liste der zuletzt veröffentlichten Workloadversionen aus diesem Featureband ausgegeben. Verwendet die --take Option, um anzugeben, wie viele angegeben werden sollen, und --format, um das Format zu ändern. + Beispiel: + dotnet workload search version --take 2 --format JSON + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. Wenn eine Workloadversion als Argument angegeben wird, wird eine Tabelle mit verschiedenen Workloads und deren Versionen für die angegebene Workloadversion ausgegeben. Verwendet die --format Option, um das Ausgabeformat zu ändern. + Beispiel: + dotnet workload search version 9.0.201 + Manifestversion des Funktionsbandmanifests für Workloadmanifest-ID + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.zählung 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aturm 8.0.100 8.2.0 + 3. Wenn mindestens eine Workload zusammen mit ihren Versionen bereitgestellt wird (indem sie mit dem Zeichen "@" verbunden werden), werden Workloadversionen ausgegeben, die mit den angegebenen Versionen übereinstimmen. Verwendet die option --take, um anzugeben, wie viele angegeben werden sollen, und --format, um das Format zu ändern. + Beispiel: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + {Locked="--take"} {Locked="--format"} {Locked="dotnet workload search version"} {Locked="workloadVersion"} The --take option must be positive. @@ -77,6 +135,11 @@ Geben Workloadmanifestversionen, die der angegebenen Workloadversion zugeordnet sind, aus. + + No workload version matching {0} was found. + Es wurde keine Workloadversion gefunden, die mit {0} übereinstimmt. + + \ No newline at end of file diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.es.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.es.xlf index f57fc3788a0e..cd9d840c212b 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.es.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.es.xlf @@ -33,9 +33,67 @@ - Output a list of the latest released workload versions. Takes the --take option to specify how many to provide and --format to alter the format. - Genera una lista de las últimas versiones de carga de trabajo publicadas. Toma la opción --take para especificar cuántos proporcionar y --format para modificar el formato. - Do not localize --take or --format + 'dotnet workload search version' has three functions depending on its argument: + 1. If no argument is specified, it outputs a list of the latest released workload versions from this feature band. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. If a workload version is provided as an argument, it outputs a table of various workloads and their versions for the specified workload version. Takes the --format option to alter the output format. + Example: + dotnet workload search version 9.0.201 + Workload manifest ID Manifest feature band Manifest Version + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. If one or more workloads are provided along with their versions (by joining them with the '@' character), it outputs workload versions that match the provided versions. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + 'dotnet workload search version' tiene tres funciones en función de su argumento: + 1. Si no se especifica ningún argumento, genera una lista de las últimas versiones de carga de trabajo publicadas de esta banda de características. Toma la opción --take para especificar cuántos proporcionar y --format para modificar el formato. + Ejemplo: + dotnet workload search version --take 2 --format JSON + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. Si se proporciona una versión de carga de trabajo como argumento, genera una tabla de varias cargas de trabajo y sus versiones para la versión de carga de trabajo especificada. Toma la opción --format para modificar el formato de salida. + Ejemplo: + dotnet workload search version 9.0.201 + Versión del manifiesto de la banda de características del manifiesto del id. del manifiesto de carga de trabajo + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.runtime 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.runtime 8.0.100 8.2.0 + 3. Si se proporcionan una o varias cargas de trabajo junto con sus versiones (al unirlas con el carácter "@"), genera versiones de carga de trabajo que coinciden con las versiones proporcionadas. Toma la opción --take para especificar cuántos proporcionar y --format para modificar el formato. + Ejemplo: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + {Locked="--take"} {Locked="--format"} {Locked="dotnet workload search version"} {Locked="workloadVersion"} The --take option must be positive. @@ -77,6 +135,11 @@ Versiones del manifiesto de carga de trabajo de salida asociadas a la versión de carga de trabajo proporcionada. + + No workload version matching {0} was found. + No se encontró ninguna versión de carga de trabajo que coincida con {0}. + + \ No newline at end of file diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.fr.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.fr.xlf index 929a846e473b..89a0daf154a8 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.fr.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.fr.xlf @@ -33,9 +33,67 @@ - Output a list of the latest released workload versions. Takes the --take option to specify how many to provide and --format to alter the format. - Affiche la liste des dernières versions de charge de travail publiées. Prend l’option --take pour spécifier le nombre à fournir et --format pour modifier le format. - Do not localize --take or --format + 'dotnet workload search version' has three functions depending on its argument: + 1. If no argument is specified, it outputs a list of the latest released workload versions from this feature band. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. If a workload version is provided as an argument, it outputs a table of various workloads and their versions for the specified workload version. Takes the --format option to alter the output format. + Example: + dotnet workload search version 9.0.201 + Workload manifest ID Manifest feature band Manifest Version + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. If one or more workloads are provided along with their versions (by joining them with the '@' character), it outputs workload versions that match the provided versions. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + « dotnet workload search version » a trois fonctions en fonction de son argument : + 1. Si aucun argument n’est spécifié, il génère une liste des dernières versions de charge de travail publiées à partir de cette bande de fonctionnalités. Prend l’option --take pour spécifier le nombre à fournir et --format pour modifier le format. + Exemple : + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. Si une version de charge de travail est fournie en tant qu’argument, elle génère une table de différentes charges de travail et de leurs versions pour la version de charge de travail spécifiée. Prend l’option --format pour modifier le format de sortie. + Exemple : + dotnet workload search version 9.0.201 + ID du manifeste de la charge de travail Manifeste de la bande de caractéristiques Version du manifeste + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. Si une ou plusieurs charges de travail sont fournies avec leurs versions (en les joignant avec le caractère « @ »), elle génère des versions de charge de travail qui correspondent aux versions fournies. Prend l’option --take pour spécifier le nombre à fournir et --format pour modifier le format. + Exemple : + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + {Locked="--take"} {Locked="--format"} {Locked="dotnet workload search version"} {Locked="workloadVersion"} The --take option must be positive. @@ -77,6 +135,11 @@ Affiche le manifeste de charge de travail associé à la version de charge de travail fournie. + + No workload version matching {0} was found. + Aucune version de charge de travail correspondant à {0} n’a été trouvée. + + \ No newline at end of file diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.it.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.it.xlf index 2775775318c1..588963ad531e 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.it.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.it.xlf @@ -33,9 +33,67 @@ - Output a list of the latest released workload versions. Takes the --take option to specify how many to provide and --format to alter the format. - Restituisce un elenco delle ultime versioni del carico di lavoro rilasciate. Accetta l'opzione --take per specificare quanti fornirne e --format per modificare il formato. - Do not localize --take or --format + 'dotnet workload search version' has three functions depending on its argument: + 1. If no argument is specified, it outputs a list of the latest released workload versions from this feature band. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. If a workload version is provided as an argument, it outputs a table of various workloads and their versions for the specified workload version. Takes the --format option to alter the output format. + Example: + dotnet workload search version 9.0.201 + Workload manifest ID Manifest feature band Manifest Version + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. If one or more workloads are provided along with their versions (by joining them with the '@' character), it outputs workload versions that match the provided versions. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + 'dotnet workload search version' ha tre funzioni a seconda del relativo argomento: + 1. Se non viene specificato alcun argomento, verrà restituito un elenco delle versioni del carico di lavoro rilasciate più recenti da questa banda di funzionalità. Accetta l'opzione --take per specificare il numero da fornire e --format per modificare il formato. + Esempio: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. Se viene fornita una versione del carico di lavoro come argomento, viene restituita una tabella di diversi carichi di lavoro e le relative versioni per la versione del carico di lavoro specificata. Accetta l'opzione --format per modificare il formato di output. + Esempio: + dotnet workload search version 9.0.201 + Versione manifesto della banda della funzionalità manifesto ID manifesto del carico di lavoro + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.di 8.0.100 8.2.0 + 3. Se vengono forniti uno o più carichi di lavoro insieme alle relative versioni (aggiungendoli con il carattere '@'), verranno restituite le versioni del carico di lavoro corrispondenti alle versioni fornite. Accetta l'opzione --take per specificare il numero da fornire e --format per modificare il formato. + Esempio: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + {Locked="--take"} {Locked="--format"} {Locked="dotnet workload search version"} {Locked="workloadVersion"} The --take option must be positive. @@ -77,6 +135,11 @@ Versioni del manifesto del carico di lavoro di output associate alla versione del carico di lavoro fornita. + + No workload version matching {0} was found. + Non è stata trovata alcuna versione del carico di lavoro corrispondente {0}. + + \ No newline at end of file diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ja.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ja.xlf index 295a1383492b..3c114debe2c0 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ja.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ja.xlf @@ -33,9 +33,67 @@ - Output a list of the latest released workload versions. Takes the --take option to specify how many to provide and --format to alter the format. - リリース済みの最新のワークロード バージョンの一覧を出力します。--take オプションを指定して提供する数を指定し、--format を指定して形式を変更します。 - Do not localize --take or --format + 'dotnet workload search version' has three functions depending on its argument: + 1. If no argument is specified, it outputs a list of the latest released workload versions from this feature band. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. If a workload version is provided as an argument, it outputs a table of various workloads and their versions for the specified workload version. Takes the --format option to alter the output format. + Example: + dotnet workload search version 9.0.201 + Workload manifest ID Manifest feature band Manifest Version + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. If one or more workloads are provided along with their versions (by joining them with the '@' character), it outputs workload versions that match the provided versions. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + 'dotnet workload search version' には、引数に応じて次の 3 つの関数があります: + 1. 引数が指定されていない場合、この機能バンドから最新のリリースされたワークロード バージョンの一覧が出力されます。--take オプションを使用して、指定する数を指定し、形式を変更 --format します。 + 例: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. ワークロード バージョンが引数として指定されている場合、指定されたワークロード バージョンのさまざまなワークロードとそのバージョンのテーブルが出力されます。--format オプションを使用して出力形式を変更します。 + 例: + dotnet workload search version 9.0.201 + ワークロード マニフェスト ID マニフェスト機能バンド マニフェスト バージョン + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.proj 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. 1 つ以上のワークロードがバージョンと一緒に提供されている場合 ('@' 文字で結合することにより)、指定されたバージョンと一致するワークロード バージョンが出力されます。--take オプションを使用して、指定する数を指定し、形式を変更する --format します。 + 例: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + {Locked="--take"} {Locked="--format"} {Locked="dotnet workload search version"} {Locked="workloadVersion"} The --take option must be positive. @@ -77,6 +135,11 @@ 指定されたワークロード バージョンに関連付けられたワークロード マニフェストのバージョンを出力します。 + + No workload version matching {0} was found. + {0} に一致するワークロード バージョンが見つかりませんでした。 + + \ No newline at end of file diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ko.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ko.xlf index dcb3a7700495..8dc61343b01e 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ko.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ko.xlf @@ -33,9 +33,67 @@ - Output a list of the latest released workload versions. Takes the --take option to specify how many to provide and --format to alter the format. - 릴리스된 최신 워크로드 버전 목록을 출력합니다. --take 옵션을 사용하여 얼마나 제공할지 지정하고 --format을 사용하여 형식을 변경합니다. - Do not localize --take or --format + 'dotnet workload search version' has three functions depending on its argument: + 1. If no argument is specified, it outputs a list of the latest released workload versions from this feature band. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. If a workload version is provided as an argument, it outputs a table of various workloads and their versions for the specified workload version. Takes the --format option to alter the output format. + Example: + dotnet workload search version 9.0.201 + Workload manifest ID Manifest feature band Manifest Version + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. If one or more workloads are provided along with their versions (by joining them with the '@' character), it outputs workload versions that match the provided versions. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + 'dotnet workload search version' 인수에 따라 세 개의 함수가 있습니다. + 1. 인수를 지정하지 않으면 이 기능 대역에서 릴리스된 최신 워크로드 버전 목록을 출력합니다. --take 옵션을 사용하여 제공할 수 있는 횟수를 지정하고 --format 형식을 변경합니다. + 예: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. 작업 버전이 인수로 제공되는 경우 지정된 워크로드 버전에 대한 다양한 워크로드 및 해당 버전의 테이블을 출력합니다. 출력 형식을 변경하려면 --format 옵션을 사용합니다. + 본보기: + dotnet workload search version 9.0.201 + 워크로드 매니페스트 ID 매니페스트 기능 밴드 매니페스트 버전 + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aggregate 8.0.100 8.2.0 + 3. 하나 이상의 워크로드가 해당 버전과 함께 제공되는 경우('@' 문자와 조인하여) 제공된 버전과 일치하는 워크로드 버전을 출력합니다. --take 옵션을 사용하여 제공할 개수를 지정하고 --format 형식을 변경합니다. + 본보기: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + {Locked="--take"} {Locked="--format"} {Locked="dotnet workload search version"} {Locked="workloadVersion"} The --take option must be positive. @@ -77,6 +135,11 @@ 제공된 워크로드 버전과 연결된 워크로드 매니페스트 버전을 출력합니다. + + No workload version matching {0} was found. + {0} 일치하는 워크로드 버전을 찾을 수 없습니다. + + \ No newline at end of file diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.pl.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.pl.xlf index 76d0c8290c8b..074856286788 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.pl.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.pl.xlf @@ -33,9 +33,67 @@ - Output a list of the latest released workload versions. Takes the --take option to specify how many to provide and --format to alter the format. - Wyświetl listę najnowszych wydanych wersji obciążenia. Przyjmuje opcję --take, aby określić, ile elementów należy podać, i polecenie --format, aby zmienić format. - Do not localize --take or --format + 'dotnet workload search version' has three functions depending on its argument: + 1. If no argument is specified, it outputs a list of the latest released workload versions from this feature band. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. If a workload version is provided as an argument, it outputs a table of various workloads and their versions for the specified workload version. Takes the --format option to alter the output format. + Example: + dotnet workload search version 9.0.201 + Workload manifest ID Manifest feature band Manifest Version + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. If one or more workloads are provided along with their versions (by joining them with the '@' character), it outputs workload versions that match the provided versions. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + 'dotnet workload search version' ma trzy funkcje zależne od argumentu: + 1. Jeśli nie zostanie określony żaden argument, zostanie wyświetlona lista najnowszych wydań wersji obciążenia z tego pasma funkcji. Przyjmuje opcję --take, aby określić, ilu elementów należy podać, i --format zmienić format. + Przykład: + dotnet workload search version --take 2 --format kod JSON + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. Jeśli wersja obciążenia zostanie podana jako argument, wyjściowa zostanie tabela różnych obciążeń i ich wersje dla określonej wersji obciążenia. Przyjmuje opcję --format, aby zmienić format wyjściowy. + Przykład: + dotnet workload search version 9.0.201 + Wersja manifestu manifestu pakietu roboczego + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.8.0.100 8.2.0 + 3. Jeśli co najmniej jedno obciążenie jest dostarczane wraz z ich wersjami (przez dołączenie ich za pomocą znaku "@"), generuje wersje obciążenia zgodne z podanymi wersjami. Przyjmuje opcję --take, aby określić, ile elementów należy podać, i --format zmienić format. + Przykład: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + {Locked="--take"} {Locked="--format"} {Locked="dotnet workload search version"} {Locked="workloadVersion"} The --take option must be positive. @@ -77,6 +135,11 @@ Wersje manifestu obciążenia wyjściowego skojarzone z udostępnioną wersją obciążenia. + + No workload version matching {0} was found. + Nie znaleziono wersji pakietu roboczego pasującej {0}. + + \ No newline at end of file diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.pt-BR.xlf index 89a9847f6790..9d5900b61b6a 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.pt-BR.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.pt-BR.xlf @@ -33,9 +33,67 @@ - Output a list of the latest released workload versions. Takes the --take option to specify how many to provide and --format to alter the format. - Gerar uma lista das versões de carga de trabalho lançadas mais recentes. Usa a opção --take para especificar quantos devem ser fornecidos e --format para alterar o formato. - Do not localize --take or --format + 'dotnet workload search version' has three functions depending on its argument: + 1. If no argument is specified, it outputs a list of the latest released workload versions from this feature band. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. If a workload version is provided as an argument, it outputs a table of various workloads and their versions for the specified workload version. Takes the --format option to alter the output format. + Example: + dotnet workload search version 9.0.201 + Workload manifest ID Manifest feature band Manifest Version + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. If one or more workloads are provided along with their versions (by joining them with the '@' character), it outputs workload versions that match the provided versions. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + 'dotnet workload search version' possui três funções dependendo de seu argumento: + 1. Se nenhum argumento for especificado, ele exibe uma lista das versões mais recentes dos workloads lançados a partir desta faixa de recursos. Aceita a opção --take para especificar quantos fornecer e --format para alterar o formato. + Exemplo: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. Se uma versão de workload for fornecida como argumento, ele exibe uma tabela de vários workloads e suas versões para a versão de workload especificada. Aceita a opção --format para alterar o formato da saída. + Exemplo: + dotnet workload search version 9.0.201 + ID de manifesto do Workload Faixa de recursos do manifesto Versão do manifesto + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. Se um ou mais workloads forem fornecidos junto com suas versões (por meio da junção com o caractere '@'), ele exibe as versões dos workloads que correspondem às versões fornecidas. Aceita a opção --take para especificar quantos fornecer e --format para alterar o formato. + Exemplo: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + {Locked="--take"} {Locked="--format"} {Locked="dotnet workload search version"} {Locked="workloadVersion"} The --take option must be positive. @@ -77,6 +135,11 @@ Versões de manifesto de carga de trabalho de saída associadas à versão de carga de trabalho fornecida. + + No workload version matching {0} was found. + Nenhuma versão de carga de trabalho {0} encontrada. + + \ No newline at end of file diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ru.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ru.xlf index 909910a65e6d..3dbb1913405c 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ru.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ru.xlf @@ -33,9 +33,67 @@ - Output a list of the latest released workload versions. Takes the --take option to specify how many to provide and --format to alter the format. - Вывод списка последних выпущенных версий рабочей нагрузки. Принимает параметр --take для указания количества и --format для изменения формата. - Do not localize --take or --format + 'dotnet workload search version' has three functions depending on its argument: + 1. If no argument is specified, it outputs a list of the latest released workload versions from this feature band. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. If a workload version is provided as an argument, it outputs a table of various workloads and their versions for the specified workload version. Takes the --format option to alter the output format. + Example: + dotnet workload search version 9.0.201 + Workload manifest ID Manifest feature band Manifest Version + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. If one or more workloads are provided along with their versions (by joining them with the '@' character), it outputs workload versions that match the provided versions. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + 'dotnet workload search version' имеет три функции в зависимости от своего аргумента: + 1. Если аргумент не указан, он выводит список последних выпущенных версий рабочей нагрузки из этого диапазона функций. Принимает параметр --take, чтобы указать количество --format и изменить формат. + Пример: + dotnet workload search version --take 2 --format JSON + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. Если в качестве аргумента указана версия рабочей нагрузки, она выводит таблицу различных рабочих нагрузок и их версии для указанной версии рабочей нагрузки. Принимает параметр --format для изменения формата выходных данных. + Пример: + dotnet workload search version 9.0.201 + Версия манифеста манифеста манифеста рабочей нагрузки + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.веб-сайт 8.0.100 8.2.0 + 3. Если одна или несколько рабочих нагрузок предоставляются вместе с их версиями (путем присоединения к ним с символом "@"), выводить версии рабочей нагрузки, соответствующие указанным версиям. Принимает параметр --take, чтобы указать, сколько нужно предоставить и --format изменить формат. + Пример: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + {Locked="--take"} {Locked="--format"} {Locked="dotnet workload search version"} {Locked="workloadVersion"} The --take option must be positive. @@ -77,6 +135,11 @@ Вывод версий манифеста рабочей нагрузки, связанных с указанной версией рабочей нагрузки. + + No workload version matching {0} was found. + Версия рабочей нагрузки, соответствующая {0}, не найдена. + + \ No newline at end of file diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.tr.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.tr.xlf index 7c094b576f4d..e6a5ebd463ec 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.tr.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.tr.xlf @@ -33,9 +33,67 @@ - Output a list of the latest released workload versions. Takes the --take option to specify how many to provide and --format to alter the format. - En son yayınlanan iş yükü sürümlerinin listesinin çıkışını görüntüler. Sağlanacak sayıyı belirtmek için --take seçeneğini, biçimi değiştirmek için ise --format seçeneğini alır. - Do not localize --take or --format + 'dotnet workload search version' has three functions depending on its argument: + 1. If no argument is specified, it outputs a list of the latest released workload versions from this feature band. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. If a workload version is provided as an argument, it outputs a table of various workloads and their versions for the specified workload version. Takes the --format option to alter the output format. + Example: + dotnet workload search version 9.0.201 + Workload manifest ID Manifest feature band Manifest Version + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. If one or more workloads are provided along with their versions (by joining them with the '@' character), it outputs workload versions that match the provided versions. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + 'dotnet workload search version' bağımsız değişkenine bağlı olarak üç işleve sahip: + 1. Bağımsız değişken belirtilmezse, bu özellik bandının en son yayınlanan iş yükü sürümlerinin bir listesini döndürür. Sağ --take belirtmek için bu seçeneği kullanır ve --format biçimi değiştirebilirsiniz. + Örnek: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. Bağımsız değişken olarak bir iş yükü sürümü sağlanırsa, belirtilen iş yükü sürümü için çeşitli iş yüklerinin ve sürümlerinin bir tablosunu çıkışını alır. Çıkış --format değiştirme seçeneğini alır. + Örnek: + dotnet workload search version 9.0.201 + İş yükü bildirimi kimliği bildirimi özellik bandı Bildirim Sürümü + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.microsoft 8.0.100 8.2.0 + 3. Bir veya daha fazla iş yükü sürümleriyle birlikte sağlanırsa ('@' karakteriyle birleşerek), sağlanan sürümlerle eşleşen iş yükü sürümleri çıkışı sağlar. Sağ --take belirtmek için bu seçeneği alır ve biçimi --format seçeneğine tıklayın. + Örnek: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + {Locked="--take"} {Locked="--format"} {Locked="dotnet workload search version"} {Locked="workloadVersion"} The --take option must be positive. @@ -77,6 +135,11 @@ Sağlanan iş yükü sürümüyle ilişkili iş yükü bildirimi sürümlerinin çıkışını görüntüler. + + No workload version matching {0} was found. + Eşleşen iş yükü {0} bulunamadı. + + \ No newline at end of file diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.zh-Hans.xlf index b880ad1ffebe..ae224af87f3d 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.zh-Hans.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.zh-Hans.xlf @@ -33,9 +33,67 @@ - Output a list of the latest released workload versions. Takes the --take option to specify how many to provide and --format to alter the format. - 输出最新发布的工作负载版本的列表。使用 --take 选项指定要提供多少,使用 --format 来更改格式。 - Do not localize --take or --format + 'dotnet workload search version' has three functions depending on its argument: + 1. If no argument is specified, it outputs a list of the latest released workload versions from this feature band. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. If a workload version is provided as an argument, it outputs a table of various workloads and their versions for the specified workload version. Takes the --format option to alter the output format. + Example: + dotnet workload search version 9.0.201 + Workload manifest ID Manifest feature band Manifest Version + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. If one or more workloads are provided along with their versions (by joining them with the '@' character), it outputs workload versions that match the provided versions. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + ‘dotnet workload search version’ 包含三个函数,具体取决于其参数: + 1. 如果未指定参数,它将输出此功能区段中最新发布的工作负载版本的列表。使用 --take 选项指定要提供的数量,使用 --format 来更改格式。 + 示例: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. 如果将工作负载版本作为参数提供,则会输出指定工作负载版本的各种工作负载及其版本的表。使用 --format 选项更改输出格式。 + 示例: + dotnet workload search version 9.0.201 + 工作负载清单 ID 清单功能区段 清单版本 + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. 如果提供了一个或多个工作负载及其版本(通过使用 ‘@’ 字符联接它们),则会输出与提供的版本匹配的工作负载版本。使用 --take 选项指定要提供的数星,使用 --format 来更改格式。 + 示例: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + {Locked="--take"} {Locked="--format"} {Locked="dotnet workload search version"} {Locked="workloadVersion"} The --take option must be positive. @@ -77,6 +135,11 @@ 输出与所提供的工作负载版本关联的工作负载清单版本。 + + No workload version matching {0} was found. + 找不到与 {0} 匹配的工作负载版本。 + + \ No newline at end of file diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.zh-Hant.xlf index 0ba94d4aba98..13a7191a8520 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.zh-Hant.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.zh-Hant.xlf @@ -33,9 +33,67 @@ - Output a list of the latest released workload versions. Takes the --take option to specify how many to provide and --format to alter the format. - 輸出最新發行的工作負載版本的清單。使用 --take 選項來指定要提供多少個,以及使用 --format 來變更格式。 - Do not localize --take or --format + 'dotnet workload search version' has three functions depending on its argument: + 1. If no argument is specified, it outputs a list of the latest released workload versions from this feature band. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. If a workload version is provided as an argument, it outputs a table of various workloads and their versions for the specified workload version. Takes the --format option to alter the output format. + Example: + dotnet workload search version 9.0.201 + Workload manifest ID Manifest feature band Manifest Version + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. If one or more workloads are provided along with their versions (by joining them with the '@' character), it outputs workload versions that match the provided versions. Takes the --take option to specify how many to provide and --format to alter the format. + Example: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + 根據其引數,'dotnet workload search version' 有三個函式: + 1. 如果未指定引數,它會從此功能帶輸出最新發行工作負載版本的清單。使用 --take 選項來指定要提供多少個,以及使用 --format 來變更格式。 + 範例: + dotnet workload search version --take 2 --format json + [{"workloadVersion":"9.0.201"},{"workloadVersion":"9.0.200.1"}] + 2. 如果提供工作負載版本做為引數,它會針對指定的工作負載版本輸出各種工作負載及其版本的表格。使用 --format 選項來變更輸出格式。 + 範例: + dotnet workload search version 9.0.201 + 工作負載資訊清單識別碼 資訊清單功能帶 資訊清單版本 + ------------------------------------------------------------------------------------------------ + microsoft.net.workload.emscripten.current 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net6 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net7 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.workload.emscripten.net8 9.0.100-rc.1 9.0.0-rc.1.24430.3 + microsoft.net.sdk.android 9.0.100-rc.1 35.0.0-rc.1.80 + microsoft.net.sdk.ios 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.maccatalyst 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.sdk.macos 9.0.100-rc.1 14.5.9270-net9-rc1 + microsoft.net.sdk.maui 9.0.100-rc.1 9.0.0-rc.1.24453.9 + microsoft.net.sdk.tvos 9.0.100-rc.1 17.5.9270-net9-rc1 + microsoft.net.workload.mono.toolchain.current 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net6 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net7 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.workload.mono.toolchain.net8 9.0.100-rc.1 9.0.0-rc.1.24431.7 + microsoft.net.sdk.aspire 8.0.100 8.2.0 + 3. 如果提供一或多個工作負載及其版本 (使用 '@' 字元聯結它們),它會輸出符合所提供版本的工作負載版本。使用 --take 選項來指定要提供多少個,以及使用 --format 來變更格式。 + 範例: + dotnet workload search version maui@9.0.0-rc.1.24453.9 ios@17.5.9270-net9-rc1 + 9.0.201 + + {Locked="--take"} {Locked="--format"} {Locked="dotnet workload search version"} {Locked="workloadVersion"} The --take option must be positive. @@ -77,6 +135,11 @@ 與提供的工作負載版本相關聯的輸出工作負載資訊清單版本。 + + No workload version matching {0} was found. + 找不到符合 {0} 的工作負載版本。 + + \ No newline at end of file diff --git a/src/Cli/dotnet/dotnet.csproj b/src/Cli/dotnet/dotnet.csproj index 82db3621e7fc..da9f09bd96c8 100644 --- a/src/Cli/dotnet/dotnet.csproj +++ b/src/Cli/dotnet/dotnet.csproj @@ -91,7 +91,6 @@ - diff --git a/src/Cli/dotnet/xlf/CommonLocalizableStrings.cs.xlf b/src/Cli/dotnet/xlf/CommonLocalizableStrings.cs.xlf index 8ae7960c4016..d7cbb15d7309 100644 --- a/src/Cli/dotnet/xlf/CommonLocalizableStrings.cs.xlf +++ b/src/Cli/dotnet/xlf/CommonLocalizableStrings.cs.xlf @@ -37,6 +37,36 @@ Zadání možností -r|--runtime a -os zároveň se nepodporuje. + + Sets the value of an environment variable. +Creates the variable if it does not exist, overrides if it does. +This will force the tests to be run in an isolated process. +This argument can be specified multiple times to provide multiple variables. + +Examples: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + Nastaví hodnotu proměnné prostředí. +Pokud proměnná neexistuje, vytvoří ji, a pokud existuje, přepíše ji. +Tímto se vynutí spuštění testů v izolovaném procesu. +Tento argument je možné zadat vícekrát a určit tak více proměnných. + +Příklady: +-e PROMĚNNÁ=abc +-e PROMĚNNÁ="hodnota s mezerami" +-e PROMĚNNÁ="hodnota;oddělená;pomocí;středníků" +-e PROM1=abc -e PROM2=def -e PROM3=ghi + + + + + NAME="VALUE" + NÁZEV="HODNOTA" + + Allows the command to stop and wait for user input or action (for example to complete authentication). Umožňuje, aby se příkaz zastavil a počkal na vstup nebo akci uživatele (například na dokončení ověření). @@ -130,6 +160,11 @@ export PATH="$PATH:{0}" Publikujte svoji aplikaci jako aplikaci závislou na architektuře. Aby bylo možné vaši aplikaci spustit, musí být na cílovém počítači nainstalovaný kompatibilní modul runtime .NET. + + Incorrectly formatted environment variables: {0} + Nesprávně formátované proměnné prostředí: {0} + + .NET Cli Options: Možnosti rozhraní příkazového řádku .NET: @@ -222,6 +257,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is Výchozí hodnota je false, ale pokud cílíte na .NET 7 nebo nižší a je zadán identifikátor modulu runtime, výchozí hodnota je true. + + Search for available workload versions or what comprises a workload version. Use 'dotnet workload search version --help' for more information. + Vyhledejte dostupné verze úlohy nebo to, co se skládá z verze úlohy. Další informace získáte pomocí 'dotnet workload search version --help'. + {Locked="dotnet workload search version --help"} + Solution Řešení diff --git a/src/Cli/dotnet/xlf/CommonLocalizableStrings.de.xlf b/src/Cli/dotnet/xlf/CommonLocalizableStrings.de.xlf index e8aed6ea1205..8095a9288eb8 100644 --- a/src/Cli/dotnet/xlf/CommonLocalizableStrings.de.xlf +++ b/src/Cli/dotnet/xlf/CommonLocalizableStrings.de.xlf @@ -37,6 +37,36 @@ Das gleichzeitige Angeben der Optionen „-r|--runtime“ und „-os“ wird nicht unterstützt. + + Sets the value of an environment variable. +Creates the variable if it does not exist, overrides if it does. +This will force the tests to be run in an isolated process. +This argument can be specified multiple times to provide multiple variables. + +Examples: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + Legt den Wert einer Umgebungsvariablen fest. +Erstellt die Variable, wenn Sie nicht vorhanden ist, und setzt sie andernfalls außer Kraft. +Dadurch wird die Ausführung der Tests in einem isolierten Prozess erzwungen. +Dieses Argument kann mehrmals angegeben werden, um mehrere Variablen bereitzustellen. + +Beispiele: +-e VARIABLE=abc +-e VARIABLE="wert mit leerzeichen" +-e VARIABLE="wert;getrennt durch;semikolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + + + + NAME="VALUE" + NAME="WERT" + + Allows the command to stop and wait for user input or action (for example to complete authentication). Hiermit wird zugelassen, dass der Befehl anhält und auf eine Benutzereingabe oder Aktion wartet (beispielsweise auf den Abschluss der Authentifizierung). @@ -130,6 +160,11 @@ export PATH="$PATH:{0}" Veröffentlichen Sie Ihre Anwendung als eine von einem Framework abhängige Anwendung. Eine kompatible .NET-Runtime muss auf dem Zielcomputer installiert sein, um Ihre Anwendung ausführen zu können. + + Incorrectly formatted environment variables: {0} + Falsch formatierte Umgebungsvariablen: {0} + + .NET Cli Options: .NET-Cli-Optionen: @@ -222,6 +257,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is Der Standardwert lautet FALSE. Wenn sie jedoch auf .NET 7 oder niedriger abzielen, lautet der Standardwert TRUE, wenn ein Laufzeitbezeichner angegeben wird. + + Search for available workload versions or what comprises a workload version. Use 'dotnet workload search version --help' for more information. + Suchen Sie nach verfügbaren Workloadversionen oder einer Workloadversion. Verwenden Sie 'dotnet workload search version --help', um weitere Informationen zu finden. + {Locked="dotnet workload search version --help"} + Solution Projektmappe diff --git a/src/Cli/dotnet/xlf/CommonLocalizableStrings.es.xlf b/src/Cli/dotnet/xlf/CommonLocalizableStrings.es.xlf index d0456889ad38..33a1bbbdd978 100644 --- a/src/Cli/dotnet/xlf/CommonLocalizableStrings.es.xlf +++ b/src/Cli/dotnet/xlf/CommonLocalizableStrings.es.xlf @@ -37,6 +37,36 @@ No se admite la especificación de las opciones '-r|--runtime' y '-os'. + + Sets the value of an environment variable. +Creates the variable if it does not exist, overrides if it does. +This will force the tests to be run in an isolated process. +This argument can be specified multiple times to provide multiple variables. + +Examples: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + Establece el valor de una variable de entorno. +Crea la variable si no existe o la reemplaza en caso de que exista. +Esto forzará la ejecución de las pruebas en un proceso aislado. +Este argumento se puede especificar varias veces para proporcionar múltiples variables. + +Ejemplos: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + + + + NAME="VALUE" + NAME="VALUE" + + Allows the command to stop and wait for user input or action (for example to complete authentication). Permite que el comando se detenga y espere la entrada o acción del usuario (por ejemplo, para autenticarse). @@ -130,6 +160,11 @@ export PATH="$PATH:{0}" Publique la aplicación como una aplicación dependiente del marco de trabajo. para ejecutar la aplicación debe instalarse un entorno de ejecución de .NET compatible en el equipo de destino. + + Incorrectly formatted environment variables: {0} + Las variables de entorno tienen un formato incorrecto: {0} + + .NET Cli Options: Opciones de la CLI de .NET: @@ -223,6 +258,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is El valor predeterminado es "false". Sin embargo, cuando el destino es .NET 7 o inferior, el valor predeterminado es "true" si se especifica un identificador en tiempo de ejecución. + + Search for available workload versions or what comprises a workload version. Use 'dotnet workload search version --help' for more information. + Busque las versiones de carga de trabajo disponibles o qué consta de una versión de carga de trabajo. Use 'dotnet workload search version --help' para obtener más información. + {Locked="dotnet workload search version --help"} + Solution Solución diff --git a/src/Cli/dotnet/xlf/CommonLocalizableStrings.fr.xlf b/src/Cli/dotnet/xlf/CommonLocalizableStrings.fr.xlf index da5f2b48c79d..b120d6e2598e 100644 --- a/src/Cli/dotnet/xlf/CommonLocalizableStrings.fr.xlf +++ b/src/Cli/dotnet/xlf/CommonLocalizableStrings.fr.xlf @@ -37,6 +37,36 @@ La spécification des options « -r |--Runtime » et « os » n’est pas prise en charge. + + Sets the value of an environment variable. +Creates the variable if it does not exist, overrides if it does. +This will force the tests to be run in an isolated process. +This argument can be specified multiple times to provide multiple variables. + +Examples: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + Définit la valeur d'une variable d'environnement. +Crée la variable si elle n'existe pas, et la remplace si elle existe. +Cela entraîne l'exécution forcée des tests dans un processus isolé. +Vous pouvez spécifier cet argument plusieurs fois pour fournir plusieurs variables. + +Exemples : +-e VARIABLE=abc +-e VARIABLE="valeur avec des espaces" +-e VARIABLE="valeur;séparée;par;des;points;virgules" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + + + + NAME="VALUE" + NAME="VALUE" + + Allows the command to stop and wait for user input or action (for example to complete authentication). Permet à la commande de s'arrêter et d'attendre une entrée ou une action de l'utilisateur (par exemple pour effectuer une authentification). @@ -130,6 +160,11 @@ export PATH="$PATH:{0}" Publiez votre application en tant qu'application dépendante du framework. Un runtime .NET compatible doit être installé sur la machine cible pour exécuter votre application. + + Incorrectly formatted environment variables: {0} + Mise en forme incorrecte des variables d’environnement : {0} + + .NET Cli Options: Options Cli .NET : @@ -223,6 +258,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is La valeur par défaut est « false ». Toutefois, lorsque vous ciblez .NET 7 ou une version antérieure, la valeur par défaut est « true » si un identificateur d’exécution est spécifié. + + Search for available workload versions or what comprises a workload version. Use 'dotnet workload search version --help' for more information. + Recherchez les versions de charge de travail disponibles ou les versions d’une charge de travail. Utilisez 'dotnet workload search version --help' pour plus d’informations. + {Locked="dotnet workload search version --help"} + Solution Solution diff --git a/src/Cli/dotnet/xlf/CommonLocalizableStrings.it.xlf b/src/Cli/dotnet/xlf/CommonLocalizableStrings.it.xlf index 84b8e63f7b0d..81cecdb1b96b 100644 --- a/src/Cli/dotnet/xlf/CommonLocalizableStrings.it.xlf +++ b/src/Cli/dotnet/xlf/CommonLocalizableStrings.it.xlf @@ -37,6 +37,36 @@ La specifica di entrambe le opzioni `-r|--runtime` e `-os` non è supportata. + + Sets the value of an environment variable. +Creates the variable if it does not exist, overrides if it does. +This will force the tests to be run in an isolated process. +This argument can be specified multiple times to provide multiple variables. + +Examples: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + Imposta il valore di una variabile di ambiente. +Crea la variabile se non esiste e la sostituisce se esiste. +In questo modo forza l'esecuzione dei test in un processo isolato. +È possibile specificare più volte questo argomento per fornire più variabili. + +Esempi: +-e VARIABLE=abc +-e VARIABLE="valore con spazi" +-e VARIABLE="valore;delimitato da;punti e virgola" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + + + + NAME="VALUE" + NAME="VALORE" + + Allows the command to stop and wait for user input or action (for example to complete authentication). Consente al comando di arrestare l'esecuzione e attendere l'input o l'azione dell'utente, ad esempio per completare l'autenticazione. @@ -130,6 +160,11 @@ export PATH="$PATH:{0}" Pubblicare l'applicazione come applicazione dipendente dal framework. Per eseguire l'applicazione, è necessario installare un runtime .NET compatibile nel computer di destinazione. + + Incorrectly formatted environment variables: {0} + Variabili di ambiente in formato non corretto: {0} + + .NET Cli Options: Opzioni dell'interfaccia della riga di comando di .NET: @@ -222,6 +257,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is Il valore predefinito è 'false'. Tuttavia, quando la destinazione è .NET 7 o una versione inferiore, il valore predefinito è 'true' se viene specificato un identificatore di runtime. + + Search for available workload versions or what comprises a workload version. Use 'dotnet workload search version --help' for more information. + Cercare le versioni del carico di lavoro disponibili o il contenuto di una versione del carico di lavoro. Per altre informazioni, usare 'dotnet workload search version --help'. + {Locked="dotnet workload search version --help"} + Solution Soluzione diff --git a/src/Cli/dotnet/xlf/CommonLocalizableStrings.ja.xlf b/src/Cli/dotnet/xlf/CommonLocalizableStrings.ja.xlf index 955e9cfc91e8..0358d2a5e60c 100644 --- a/src/Cli/dotnet/xlf/CommonLocalizableStrings.ja.xlf +++ b/src/Cli/dotnet/xlf/CommonLocalizableStrings.ja.xlf @@ -37,6 +37,36 @@ `-r|--runtime` および `-os` オプションの両方を指定することはサポートされていません。 + + Sets the value of an environment variable. +Creates the variable if it does not exist, overrides if it does. +This will force the tests to be run in an isolated process. +This argument can be specified multiple times to provide multiple variables. + +Examples: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + 環境変数の値を設定します。 +変数が存在しない場合は作成され、存在する場合はオーバーライドされます。 +これにより、テストは強制的に分離プロセスで実行されます。 +この引数は、複数の変数を指定するために複数回指定できます。 + +例: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + + + + NAME="VALUE" + NAME="VALUE" + + Allows the command to stop and wait for user input or action (for example to complete authentication). コマンドを停止して、ユーザーの入力またはアクション (認証の完了など) を待機できるようにします。 @@ -130,6 +160,11 @@ export PATH="$PATH:{0}" アプリケーションをフレームワーク依存アプリケーションとして公開します。アプリケーションを実行するには、対象のコンピューターで互換性のある .NET ランタイムをインストールする必要があります。 + + Incorrectly formatted environment variables: {0} + 環境変数の形式が正しくありません: {0} + + .NET Cli Options: .NET CLI オプション: @@ -222,6 +257,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is 既定値は 'false' です。しかし、.NET 7 以前が対象の場合、ランタイム識別子が指定されていれば、既定値は 'true' です。 + + Search for available workload versions or what comprises a workload version. Use 'dotnet workload search version --help' for more information. + 利用可能なワークロード バージョン、またはワークロード バージョンを構成するものを検索します。詳細については、'dotnet workload search version --help' を使用してください。 + {Locked="dotnet workload search version --help"} + Solution ソリューション diff --git a/src/Cli/dotnet/xlf/CommonLocalizableStrings.ko.xlf b/src/Cli/dotnet/xlf/CommonLocalizableStrings.ko.xlf index d26185296366..1156062d22c6 100644 --- a/src/Cli/dotnet/xlf/CommonLocalizableStrings.ko.xlf +++ b/src/Cli/dotnet/xlf/CommonLocalizableStrings.ko.xlf @@ -37,6 +37,36 @@ `-r|--runtime` 및 `-os` 옵션을 모두 지정하는 것은 지원되지 않습니다. + + Sets the value of an environment variable. +Creates the variable if it does not exist, overrides if it does. +This will force the tests to be run in an isolated process. +This argument can be specified multiple times to provide multiple variables. + +Examples: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + 환경 변수의 값을 설정합니다. +변수가 없는 경우 변수를 만들고, 변수가 있으면 재정의합니다. +이는 테스트가 격리된 프로세스에서 강제로 실행되도록 합니다. +이 인수를 여러 번 지정하여 여러 변수를 제공할 수 있습니다. + +예: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + + + + NAME="VALUE" + NAME="VALUE" + + Allows the command to stop and wait for user input or action (for example to complete authentication). 명령을 중지하고 사용자 입력 또는 작업을 기다리도록 허용합니다(예: 인증 완료). @@ -130,6 +160,11 @@ export PATH="$PATH:{0}" 애플리케이션을 프레임워크 종속 애플리케이션으로 게시합니다. 애플리케이션을 실행하려면 호환되는 .NET 런타임이 대상 시스템에 설치되어 있어야 합니다. + + Incorrectly formatted environment variables: {0} + 형식이 잘못된 환경 변수: {0} + + .NET Cli Options: .NET Cli 옵션: @@ -223,6 +258,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is 기본값은 'false'입니다. 그러나 .NET 7 이하를 대상으로 하고 런타임 식별자를 지정하는 경우 기본값은 'true'입니다. + + Search for available workload versions or what comprises a workload version. Use 'dotnet workload search version --help' for more information. + 사용 가능한 워크로드 버전 또는 워크로드 버전을 구성하는 항목을 검색합니다. 자세한 내용을 보려면 'dotnet workload search version --help' 사용하십시오. + {Locked="dotnet workload search version --help"} + Solution 솔루션 diff --git a/src/Cli/dotnet/xlf/CommonLocalizableStrings.pl.xlf b/src/Cli/dotnet/xlf/CommonLocalizableStrings.pl.xlf index 091c83288270..91ec27aa7c57 100644 --- a/src/Cli/dotnet/xlf/CommonLocalizableStrings.pl.xlf +++ b/src/Cli/dotnet/xlf/CommonLocalizableStrings.pl.xlf @@ -37,6 +37,36 @@ Określanie opcji „-r|--runtime” i „-os” nie jest obsługiwane. + + Sets the value of an environment variable. +Creates the variable if it does not exist, overrides if it does. +This will force the tests to be run in an isolated process. +This argument can be specified multiple times to provide multiple variables. + +Examples: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + Ustawia wartość zmiennej środowiskowej. +Jeśli zmienna nie istnieje, tworzy ją, a jeśli istnieje, przesłania. +Wymusi to uruchamianie testów w izolowanym procesie. +Ten argument można określić wiele razy w celu podania wielu wartości. + +Przykłady: +-e ZMIENNA=abc +-e ZMIENNA="wartość ze spacjami" +-e ZMIENNA="wartości;rozdzielone;średnikami" +-e ZM1=abc -e ZM2=def -e ZM3=ghi + + + + + NAME="VALUE" + NAZWA="WARTOŚĆ" + + Allows the command to stop and wait for user input or action (for example to complete authentication). Zezwala poleceniu na zatrzymanie działania i zaczekanie na wprowadzenie danych lub wykonanie akcji przez użytkownika (na przykład ukończenie uwierzytelniania). @@ -130,6 +160,11 @@ export PATH="$PATH:{0}" Opublikuj aplikację jako aplikację zależną od frameworku. Aby można było uruchomić aplikację, na maszynie docelowej musi być zainstalowane zgodne środowisko uruchomieniowe platformy .NET. + + Incorrectly formatted environment variables: {0} + Niepoprawnie sformatowane zmienne środowiskowe: {0} + + .NET Cli Options: Opcje interfejsu wiersza polecenia platformy .NET: @@ -222,6 +257,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is Wartość domyślna to „false”. Jednak w przypadku określania wartości docelowej platformy .NET 7 lub niższej wartość domyślna to „true”, jeśli określono identyfikator środowiska uruchomieniowego. + + Search for available workload versions or what comprises a workload version. Use 'dotnet workload search version --help' for more information. + Wyszukaj dostępne wersje obciążenia lub wersję obciążenia. Aby uzyskać więcej informacji, użyj 'dotnet workload search version --help'. + {Locked="dotnet workload search version --help"} + Solution Rozwiązanie diff --git a/src/Cli/dotnet/xlf/CommonLocalizableStrings.pt-BR.xlf b/src/Cli/dotnet/xlf/CommonLocalizableStrings.pt-BR.xlf index 2a82fe3a1562..5e173f0ed9fd 100644 --- a/src/Cli/dotnet/xlf/CommonLocalizableStrings.pt-BR.xlf +++ b/src/Cli/dotnet/xlf/CommonLocalizableStrings.pt-BR.xlf @@ -37,6 +37,36 @@ Não há suporte para especificar as opções '-r |--runtime ' e '-a |--os '. + + Sets the value of an environment variable. +Creates the variable if it does not exist, overrides if it does. +This will force the tests to be run in an isolated process. +This argument can be specified multiple times to provide multiple variables. + +Examples: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + Define o valor de uma variável de ambiente. +Criará a variável quando ela não existir e a substituirá quando existir. +Isso forçará a execução dos testes em um processo isolado. +Esse argumento pode ser especificado várias vezes para fornecer várias variáveis. + +Exemplos: +-e VARIABLE=abc +-e VARIABLE="valor com espaços" +-e VARIABLE="valor;separado com;ponto e vírgula" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + + + + NAME="VALUE" + NAME="VALUE" + + Allows the command to stop and wait for user input or action (for example to complete authentication). Permite que o comando seja interrompido e aguarde a ação ou entrada do usuário (por exemplo, para concluir a autenticação). @@ -130,6 +160,11 @@ export PATH="$PATH:{0}" Publique o seu aplicativo como um aplicativo dependente de estrutura. Um runtime do .NET compatível precisa ser instalado no computador de destino para executar o aplicativo. + + Incorrectly formatted environment variables: {0} + Variáveis de ambiente formatadas incorretamente: {0} + + .NET Cli Options: Opções da CLI do .NET: @@ -222,6 +257,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is O padrão é falso.' No entanto, ao direcionar o .NET 7 ou inferior, o padrão é 'verdadeiro' se um identificador de tempo de execução for especificado. + + Search for available workload versions or what comprises a workload version. Use 'dotnet workload search version --help' for more information. + Pesquise versões de carga de trabalho disponíveis ou o que compõe uma versão de carga de trabalho. Use 'dotnet workload search version --help' para obter mais informações. + {Locked="dotnet workload search version --help"} + Solution Solução diff --git a/src/Cli/dotnet/xlf/CommonLocalizableStrings.ru.xlf b/src/Cli/dotnet/xlf/CommonLocalizableStrings.ru.xlf index 30524ccfe60c..552bd70a2a75 100644 --- a/src/Cli/dotnet/xlf/CommonLocalizableStrings.ru.xlf +++ b/src/Cli/dotnet/xlf/CommonLocalizableStrings.ru.xlf @@ -37,6 +37,36 @@ Указание параметров "-r|--runtime" и "-os" не поддерживается. + + Sets the value of an environment variable. +Creates the variable if it does not exist, overrides if it does. +This will force the tests to be run in an isolated process. +This argument can be specified multiple times to provide multiple variables. + +Examples: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + Устанавливает значение переменной среды. +Если переменной среды не существует, она создается. Если переменная среды существует, она переопределяется. +Этот аргумент подразумевает принудительное выполнение тестов в изолированном процессе. +Этот аргумент может быть указан несколько раз для нескольких переменных среды. + +Примеры: +-e VARIABLE=abc +-e VARIABLE="значение с пробелами" +-e VARIABLE="значение;разделенное;точками;с;запятыми" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + + + + NAME="VALUE" + NAME="VALUE" + + Allows the command to stop and wait for user input or action (for example to complete authentication). Позволяет остановить команду и ожидать ввода или действия пользователя (например, для проверки подлинности). @@ -130,6 +160,11 @@ export PATH="$PATH:{0}" Опубликуйте приложение как зависимое от платформы. Для запуска приложения на целевом компьютере должна быть установлена совместимая среда выполнения .NET. + + Incorrectly formatted environment variables: {0} + Неправильный формат переменных среды: {0} + + .NET Cli Options: Параметры CLI .NET: @@ -222,6 +257,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is Значение по умолчанию — "false". Однако для .NET 7 или более ранней версии значение по умолчанию — "true", если указан идентификатор среды выполнения. + + Search for available workload versions or what comprises a workload version. Use 'dotnet workload search version --help' for more information. + Поиск доступных версий рабочей нагрузки или версии рабочей нагрузки. Используйте 'dotnet workload search version --help' для получения дополнительных сведений. + {Locked="dotnet workload search version --help"} + Solution Решение diff --git a/src/Cli/dotnet/xlf/CommonLocalizableStrings.tr.xlf b/src/Cli/dotnet/xlf/CommonLocalizableStrings.tr.xlf index 2cd50917f9fc..f178beb0ab02 100644 --- a/src/Cli/dotnet/xlf/CommonLocalizableStrings.tr.xlf +++ b/src/Cli/dotnet/xlf/CommonLocalizableStrings.tr.xlf @@ -37,6 +37,36 @@ Hem `-r|--runtime` hem de `-os` seçeneğinin belirtilmesi desteklenmiyor. + + Sets the value of an environment variable. +Creates the variable if it does not exist, overrides if it does. +This will force the tests to be run in an isolated process. +This argument can be specified multiple times to provide multiple variables. + +Examples: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + Bir ortam değişkeninin değerini ayarlar. +Değişken yoksa oluşturur, varsa değişkeni geçersiz kılar. +Bu, testleri yalıtılmış bir işlemde çalıştırılmaya zorlar. +Bu bağımsız değişken, birden çok değişken sağlamak için birden çok kez belirtilebilir. + +Örnek: +-e DEĞİŞKEN=abc +-e DEĞİŞKEN="boşluk içeren değerler" +-e DEĞİŞKEN="noktalı virgülle;ayrılmış;değerler" +-e DEĞ1=abc -e DEĞ2=def -e DEĞ3=ghi + + + + + NAME="VALUE" + AD="DEĞER" + + Allows the command to stop and wait for user input or action (for example to complete authentication). Komutun durup kullanıcı girişini veya eylemini (örneğin, kimlik doğrulamasının tamamlanmasını) beklemesine izin verir . @@ -130,6 +160,11 @@ export PATH="$PATH:{0}" Uygulamanızı çerçeveye bağımlı bir uygulama olarak yayımlayın. Uygulamanızı çalıştırmak için hedef makineye uyumlu bir .NET çalışma zamanı yüklenmelidir. + + Incorrectly formatted environment variables: {0} + Yanlış biçimlendirilmiş ortam değişkenleri: {0} + + .NET Cli Options: .NET Cli Seçenekleri: @@ -222,6 +257,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is Varsayılan değer 'false' olur. Ancak çalışma zamanı tanımlayıcısı belirtildiyse .NET 7 veya altı projeler hedeflenirken varsayılan değer 'true' olur. + + Search for available workload versions or what comprises a workload version. Use 'dotnet workload search version --help' for more information. + Kullanılabilir iş yükü sürümlerini veya iş yükü sürümünü oluşturanları arayın. Daha fazla 'dotnet workload search version --help' için bu uygulamayı kullanın. + {Locked="dotnet workload search version --help"} + Solution Çözüm diff --git a/src/Cli/dotnet/xlf/CommonLocalizableStrings.zh-Hans.xlf b/src/Cli/dotnet/xlf/CommonLocalizableStrings.zh-Hans.xlf index 2345a2ae6ecd..7eb4a1bbe312 100644 --- a/src/Cli/dotnet/xlf/CommonLocalizableStrings.zh-Hans.xlf +++ b/src/Cli/dotnet/xlf/CommonLocalizableStrings.zh-Hans.xlf @@ -37,6 +37,36 @@ 不支持同时指定“-r |--runtime”和“-os”选项。 + + Sets the value of an environment variable. +Creates the variable if it does not exist, overrides if it does. +This will force the tests to be run in an isolated process. +This argument can be specified multiple times to provide multiple variables. + +Examples: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + 设置环境变量的值。 +如果该变量不存在,则创建它;如果它已存在,则替代它。 +这将在隔离的进程中强制运行测试。 +可多次指定此参数来提供多个变量。 + +示例: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + + + + NAME="VALUE" + NAME="VALUE" + + Allows the command to stop and wait for user input or action (for example to complete authentication). 允许命令停止和等待用户输入或操作(例如,用以完成身份验证)。 @@ -130,6 +160,11 @@ export PATH="$PATH:{0}" 将应用程序发布为依赖框架的应用程序。目标计算机上必须安装兼容的 .NET 运行时才能运行该应用程序。 + + Incorrectly formatted environment variables: {0} + 环境变量格式不正确: {0} + + .NET Cli Options: .NET Cli 选项: @@ -222,6 +257,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is 默认值为 "false"。但目标为 .NET 7 或更低版本时,如果指定了运行时标识符,则默认值为 "true"。 + + Search for available workload versions or what comprises a workload version. Use 'dotnet workload search version --help' for more information. + 搜索可用的工作负载版本或包含工作负载版本的版本。有关详细信息,请使用 'dotnet workload search version --help'。 + {Locked="dotnet workload search version --help"} + Solution 解决方案 diff --git a/src/Cli/dotnet/xlf/CommonLocalizableStrings.zh-Hant.xlf b/src/Cli/dotnet/xlf/CommonLocalizableStrings.zh-Hant.xlf index aff0bb272f7f..ff4b5bcc657e 100644 --- a/src/Cli/dotnet/xlf/CommonLocalizableStrings.zh-Hant.xlf +++ b/src/Cli/dotnet/xlf/CommonLocalizableStrings.zh-Hant.xlf @@ -37,6 +37,36 @@ 不支援同時指定 `-r|--runtime` 與 `-os` 選項。 + + Sets the value of an environment variable. +Creates the variable if it does not exist, overrides if it does. +This will force the tests to be run in an isolated process. +This argument can be specified multiple times to provide multiple variables. + +Examples: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + 設定環境變數的值。 +若變數不存在,則加以建立; 若有,則予以覆寫。 +這會強制在隔離流程中執行測試。 +此引數可多次指定,以提供多項變數。 + +範例: +-e VARIABLE=abc +-e VARIABLE="value with spaces" +-e VARIABLE="value;seperated with;semicolons" +-e VAR1=abc -e VAR2=def -e VAR3=ghi + + + + + NAME="VALUE" + NAME="VALUE" + + Allows the command to stop and wait for user input or action (for example to complete authentication). 允許命令停止並等候使用者輸入或動作 (例如: 完成驗證)。 @@ -130,6 +160,11 @@ export PATH="$PATH:{0}" 將您的應用程式發佈為架構相依的應用程式。必須在目標機器上安裝相容的 .NET 執行階段,才能執行您的應用程式。 + + Incorrectly formatted environment variables: {0} + 環境變數格式不正確: {0} + + .NET Cli Options: .NET CLI 選項: @@ -222,6 +257,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is 預設值為 'false'。不過,當目標為 .NET 7 或更低版本時,如有指定執行階段識別碼,則預設值為 'true'。 + + Search for available workload versions or what comprises a workload version. Use 'dotnet workload search version --help' for more information. + 搜尋可用的工作負載版本或組成工作負載版本的版本。如需詳細資訊,請使用 'dotnet workload search version --help'。 + {Locked="dotnet workload search version --help"} + Solution 解決方案 diff --git a/src/Common/CliFolderPathCalculatorCore.cs b/src/Common/CliFolderPathCalculatorCore.cs index fad9b944281d..ccdac9fd0282 100644 --- a/src/Common/CliFolderPathCalculatorCore.cs +++ b/src/Common/CliFolderPathCalculatorCore.cs @@ -7,8 +7,6 @@ static class CliFolderPathCalculatorCore { public const string DotnetHomeVariableName = "DOTNET_CLI_HOME"; public const string DotnetProfileDirectoryName = ".dotnet"; - public static readonly string PlatformHomeVariableName = - RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "USERPROFILE" : "HOME"; public static string? GetDotnetUserProfileFolderPath() { @@ -26,14 +24,10 @@ static class CliFolderPathCalculatorCore var home = Environment.GetEnvironmentVariable(DotnetHomeVariableName); if (string.IsNullOrEmpty(home)) { - home = Environment.GetEnvironmentVariable(PlatformHomeVariableName); + home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); if (string.IsNullOrEmpty(home)) { - home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); - if (string.IsNullOrEmpty(home)) - { - return null; - } + return null; } } diff --git a/src/Common/WorkloadSetVersion.cs b/src/Common/WorkloadSetVersion.cs index 907b9f5b9f42..6e21cde35855 100644 --- a/src/Common/WorkloadSetVersion.cs +++ b/src/Common/WorkloadSetVersion.cs @@ -11,6 +11,11 @@ static class WorkloadSetVersion private static string[] SeparateCoreComponents(string workloadSetVersion, out string[] sections) { sections = workloadSetVersion.Split(['-', '+'], 2); + if (sections.Length < 1) + { + return []; + } + return sections[0].Split('.'); } diff --git a/src/Compatibility/ApiCompat/Microsoft.DotNet.ApiCompat.Shared/ApiCompatServiceProvider.cs b/src/Compatibility/ApiCompat/Microsoft.DotNet.ApiCompat.Shared/ApiCompatServiceProvider.cs index 4edb495c0e5d..6d51ecc24a23 100644 --- a/src/Compatibility/ApiCompat/Microsoft.DotNet.ApiCompat.Shared/ApiCompatServiceProvider.cs +++ b/src/Compatibility/ApiCompat/Microsoft.DotNet.ApiCompat.Shared/ApiCompatServiceProvider.cs @@ -30,21 +30,20 @@ public ApiCompatServiceProvider(Func logFa AccessibilitySymbolFilter accessibilitySymbolFilter = new(respectInternals); SymbolEqualityComparer symbolEqualityComparer = new(); - // The attribute data symbol filter is a composite that contains both the accessibility - // symbol filter and the doc id symbol filter. - CompositeSymbolFilter attributeDataSymbolFilter = new(accessibilitySymbolFilter); - if (excludeAttributesFiles is not null) - { - attributeDataSymbolFilter.Add(new DocIdSymbolFilter(excludeAttributesFiles)); - } + ISymbolFilter attributeDataSymbolFilter = SymbolFilterFactory.GetFilterFromFiles( + apiExclusionFilePaths: excludeAttributesFiles, + accessibilitySymbolFilter: accessibilitySymbolFilter, + respectInternals: respectInternals); + + AttributeDataEqualityComparer attributeDataEqualityComparer = new(symbolEqualityComparer, + new TypedConstantEqualityComparer(symbolEqualityComparer)); ApiComparerSettings apiComparerSettings = new( - accessibilitySymbolFilter, - symbolEqualityComparer, - attributeDataSymbolFilter, - new AttributeDataEqualityComparer(symbolEqualityComparer, - new TypedConstantEqualityComparer(symbolEqualityComparer)), - respectInternals); + symbolFilter: accessibilitySymbolFilter, + symbolEqualityComparer: symbolEqualityComparer, + attributeDataSymbolFilter: attributeDataSymbolFilter, + attributeDataEqualityComparer: attributeDataEqualityComparer, + includeInternalSymbols: respectInternals); return new ApiCompatRunner(SuppressibleLog, SuppressionEngine, diff --git a/src/Compatibility/ApiCompat/Microsoft.DotNet.ApiCompatibility/DifferenceVisitor.cs b/src/Compatibility/ApiCompat/Microsoft.DotNet.ApiCompatibility/DifferenceVisitor.cs index 2b2fd9ef8e92..4bc4e335d1e8 100644 --- a/src/Compatibility/ApiCompat/Microsoft.DotNet.ApiCompatibility/DifferenceVisitor.cs +++ b/src/Compatibility/ApiCompat/Microsoft.DotNet.ApiCompatibility/DifferenceVisitor.cs @@ -58,13 +58,6 @@ public void Visit(IAssemblyMapper assembly) { Visit(@namespace); } - - // After visiting the assembly, the assembly mapper will contain any assembly load errors that happened - // when trying to resolve type forwarded types. If there were any, we add them to the diagnostic bag next. - foreach (CompatDifference item in assembly.AssemblyLoadErrors) - { - _compatDifferences.Add(item); - } } /// diff --git a/src/Compatibility/ApiCompat/Microsoft.DotNet.ApiCompatibility/Mapping/AssemblyMapper.cs b/src/Compatibility/ApiCompat/Microsoft.DotNet.ApiCompatibility/Mapping/AssemblyMapper.cs index 7646c1628ad0..1e4e6a7a14e9 100644 --- a/src/Compatibility/ApiCompat/Microsoft.DotNet.ApiCompatibility/Mapping/AssemblyMapper.cs +++ b/src/Compatibility/ApiCompat/Microsoft.DotNet.ApiCompatibility/Mapping/AssemblyMapper.cs @@ -21,14 +21,10 @@ public class AssemblyMapper(IRuleRunner ruleRunner, IAssemblySetMapper? containingAssemblySet = null) : ElementMapper>(ruleRunner, settings, rightSetSize), IAssemblyMapper { private Dictionary? _namespaces; - private readonly List _assemblyLoadErrors = []; /// public IAssemblySetMapper? ContainingAssemblySet { get; } = containingAssemblySet; - /// - public IEnumerable AssemblyLoadErrors => _assemblyLoadErrors; - /// public IEnumerable GetNamespaces() { diff --git a/src/Compatibility/ApiCompat/Microsoft.DotNet.ApiCompatibility/Mapping/IAssemblyMapper.cs b/src/Compatibility/ApiCompat/Microsoft.DotNet.ApiCompatibility/Mapping/IAssemblyMapper.cs index c8e1674e94bc..3a9154f53537 100644 --- a/src/Compatibility/ApiCompat/Microsoft.DotNet.ApiCompatibility/Mapping/IAssemblyMapper.cs +++ b/src/Compatibility/ApiCompat/Microsoft.DotNet.ApiCompatibility/Mapping/IAssemblyMapper.cs @@ -17,11 +17,6 @@ public interface IAssemblyMapper : IElementMapper IAssemblySetMapper? ContainingAssemblySet { get; } - /// - /// Gets the assembly load errors that happened when trying to follow type forwards. - /// - IEnumerable AssemblyLoadErrors { get; } - /// /// Gets the mappers for the namespaces contained in and /// diff --git a/src/Compatibility/Directory.Packages.props b/src/Compatibility/Directory.Packages.props index 3a07bbe661c3..9898fda73ffd 100644 --- a/src/Compatibility/Directory.Packages.props +++ b/src/Compatibility/Directory.Packages.props @@ -8,4 +8,8 @@ - \ No newline at end of file + + + + + diff --git a/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI.Task/GenAPITask.cs b/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI.Task/GenAPITask.cs index 6348a3fb8d4d..674c6f68b212 100644 --- a/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI.Task/GenAPITask.cs +++ b/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI.Task/GenAPITask.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using Microsoft.Build.Framework; using Microsoft.DotNet.ApiSymbolExtensions.Logging; using Microsoft.NET.Build.Tasks; @@ -62,17 +63,18 @@ public class GenAPITask : TaskBase /// protected override void ExecuteCore() { + Debug.Assert(Assemblies != null, "Assemblies cannot be null."); + GenAPIApp.Run(new MSBuildLog(Log), - Assemblies!, - AssemblyReferences, - OutputPath, - HeaderFile, - ExceptionMessage, - ExcludeApiFiles, - ExcludeAttributesFiles, - RespectInternals, - IncludeAssemblyAttributes - ); + Assemblies, + AssemblyReferences, + OutputPath, + HeaderFile, + ExceptionMessage, + ExcludeApiFiles, + ExcludeAttributesFiles, + RespectInternals, + IncludeAssemblyAttributes); } } } diff --git a/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI.Tool/Program.cs b/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI.Tool/Program.cs index dd2edbcbbd94..c511b14c4d10 100644 --- a/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI.Tool/Program.cs +++ b/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI.Tool/Program.cs @@ -97,15 +97,22 @@ static int Main(string[] args) rootCommand.SetAction((ParseResult parseResult) => { - GenAPIApp.Run(new ConsoleLog(MessageImportance.Normal), - parseResult.GetValue(assembliesOption)!, + bool respectInternals = parseResult.GetValue(respectInternalsOption); + + ILog log = new ConsoleLog(MessageImportance.Normal); + + string[]? assemblies = parseResult.GetValue(assembliesOption); + Debug.Assert(assemblies != null, "Assemblies cannot be null."); + + GenAPIApp.Run(log, + assemblies, parseResult.GetValue(assemblyReferencesOption), parseResult.GetValue(outputPathOption), parseResult.GetValue(headerFileOption), parseResult.GetValue(exceptionMessageOption), parseResult.GetValue(excludeApiFilesOption), parseResult.GetValue(excludeAttributesFilesOption), - parseResult.GetValue(respectInternalsOption), + respectInternals, parseResult.GetValue(includeAssemblyAttributesOption) ); }); diff --git a/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/CSharpAssemblyDocumentGenerator.cs b/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/CSharpAssemblyDocumentGenerator.cs new file mode 100644 index 000000000000..7df552851bd3 --- /dev/null +++ b/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/CSharpAssemblyDocumentGenerator.cs @@ -0,0 +1,376 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Immutable; +using System.Reflection; +using System.Runtime.CompilerServices; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Formatting; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Editing; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Simplification; +using Microsoft.DotNet.ApiSymbolExtensions; +using Microsoft.DotNet.ApiSymbolExtensions.Filtering; +using Microsoft.DotNet.ApiSymbolExtensions.Logging; +using Microsoft.DotNet.GenAPI.SyntaxRewriter; + +namespace Microsoft.DotNet.GenAPI; + +/// +/// A class that generates the C# document and syntax trees of a specified collection of assemblies. +/// +public sealed class CSharpAssemblyDocumentGenerator +{ + private readonly ILog _log; + private readonly IAssemblySymbolLoader _loader; + private readonly ISymbolFilter _symbolFilter; + private readonly ISymbolFilter _attributeDataSymbolFilter; + private readonly string? _exceptionMessage; + private readonly bool _includeAssemblyAttributes; + private readonly AdhocWorkspace _adhocWorkspace; + private readonly SyntaxGenerator _syntaxGenerator; + private readonly IEnumerable? _metadataReferences; + private readonly bool _addPartialModifier; + private readonly bool _hideImplicitDefaultConstructors; + private readonly CSharpCompilationOptions _compilationOptions; + + /// + /// Initializes a new instance of the class. + /// + /// The logger to use. + /// The assembly symbol loader to use. + /// The symbol filter to use. + /// The attribute data symbol filter to use. + /// The optional exception message to use. + /// Whether to include assembly attributes or not. + /// The metadata references to use. The default value is . + /// The optional diagnostic options to use. The default value is . + /// Whether to add the partial modifier or not. The default value is . + /// Whether to hide implicit default constructors or not. The default value is . + public CSharpAssemblyDocumentGenerator(ILog log, + IAssemblySymbolLoader loader, + ISymbolFilter symbolFilter, + ISymbolFilter attributeDataSymbolFilter, + string? exceptionMessage, + bool includeAssemblyAttributes, + IEnumerable? metadataReferences = null, + IEnumerable>? diagnosticOptions = null, + bool addPartialModifier = true, + bool hideImplicitDefaultConstructors = true) + { + _log = log; + _loader = loader; + _symbolFilter = symbolFilter; + _attributeDataSymbolFilter = attributeDataSymbolFilter; + _exceptionMessage = exceptionMessage; + _includeAssemblyAttributes = includeAssemblyAttributes; + _adhocWorkspace = new AdhocWorkspace(); + _syntaxGenerator = SyntaxGenerator.GetGenerator(_adhocWorkspace, LanguageNames.CSharp); + _metadataReferences = metadataReferences; + _addPartialModifier = addPartialModifier; + _hideImplicitDefaultConstructors = hideImplicitDefaultConstructors; + + _compilationOptions = new CSharpCompilationOptions( + OutputKind.DynamicallyLinkedLibrary, + nullableContextOptions: NullableContextOptions.Enable, + specificDiagnosticOptions: diagnosticOptions); + } + + /// + /// Returns the configured source code document for the specified assembly symbol. + /// + /// The assembly symbol that represents the loaded assembly. + /// The source code document instance of the specified assembly symbol. + public Document GetDocumentForAssembly(IAssemblySymbol assemblySymbol) + { + Project project = _adhocWorkspace.AddProject(ProjectInfo.Create( + ProjectId.CreateNewId(), VersionStamp.Create(), assemblySymbol.Name, assemblySymbol.Name, LanguageNames.CSharp, + compilationOptions: _compilationOptions)); + project = project.AddMetadataReferences(_metadataReferences ?? _loader.MetadataReferences); + + IEnumerable namespaceSymbols = EnumerateNamespaces(assemblySymbol).Where(_symbolFilter.Include); + List namespaceSyntaxNodes = []; + + foreach (INamespaceSymbol namespaceSymbol in namespaceSymbols.Order()) + { + SyntaxNode? syntaxNode = Visit(namespaceSymbol); + + if (syntaxNode is not null) + { + namespaceSyntaxNodes.Add(syntaxNode); + } + } + + SyntaxNode compilationUnit = _syntaxGenerator.CompilationUnit(namespaceSyntaxNodes) + .WithAdditionalAnnotations(Formatter.Annotation, Simplifier.Annotation) + .Rewrite(new TypeDeclarationCSharpSyntaxRewriter(_addPartialModifier)) + .Rewrite(new BodyBlockCSharpSyntaxRewriter(_exceptionMessage)); + + if (_includeAssemblyAttributes) + { + compilationUnit = GenerateAssemblyAttributes(assemblySymbol, compilationUnit); + } + + compilationUnit = GenerateForwardedTypeAssemblyAttributes(assemblySymbol, compilationUnit); + compilationUnit = compilationUnit.NormalizeWhitespace(eol: Environment.NewLine); + + Document document = project.AddDocument(assemblySymbol.Name, compilationUnit); + document = Simplifier.ReduceAsync(document).Result; + document = Formatter.FormatAsync(document, DefineFormattingOptions()).Result; + + return document; + } + + /// + /// Returns the formatted root syntax node for the specified document. + /// + /// A source code document instance. + /// The root syntax node of the specified document. + public SyntaxNode GetFormattedRootNodeForDocument(Document document) => document.GetSyntaxRootAsync().Result!.Rewrite(new SingleLineStatementCSharpSyntaxRewriter()); + + private SyntaxNode? Visit(INamespaceSymbol namespaceSymbol) + { + SyntaxNode namespaceNode = _syntaxGenerator.NamespaceDeclaration(namespaceSymbol.ToDisplayString()); + + IEnumerable typeMembers = namespaceSymbol.GetTypeMembers().Where(_symbolFilter.Include); + if (!typeMembers.Any()) + { + return null; + } + + foreach (INamedTypeSymbol typeMember in typeMembers.Order()) + { + SyntaxNode typeDeclaration = _syntaxGenerator + .DeclarationExt(typeMember, _symbolFilter) + .AddMemberAttributes(_syntaxGenerator, typeMember, _attributeDataSymbolFilter); + + typeDeclaration = Visit(typeDeclaration, typeMember); + + namespaceNode = _syntaxGenerator.AddMembers(namespaceNode, typeDeclaration); + } + + return namespaceNode; + } + + // Name hiding through inheritance occurs when classes or structs redeclare names that were inherited from base classes. This type of name hiding takes one of the following forms: + // - A constant, field, property, event, or type introduced in a class or struct hides all base class members with the same name. + // - A method introduced in a class or struct hides all non-method base class members with the same name, and all base class methods with the same signature(§7.6). + // - An indexer introduced in a class or struct hides all base class indexers with the same signature(§7.6) . + private bool HidesBaseMember(ISymbol member) + { + if (member.IsOverride) + { + return false; + } + + if (member.ContainingType.BaseType is not INamedTypeSymbol baseType) + { + return false; + } + + if (member is IMethodSymbol method) + { + if (method.MethodKind == MethodKind.ExplicitInterfaceImplementation) + { + return false; + } + + // If they're methods, compare their names and signatures. + return baseType.GetMembers(member.Name) + .Any(baseMember => _symbolFilter.Include(baseMember) && + (baseMember.Kind != SymbolKind.Method || + method.SignatureEquals((IMethodSymbol)baseMember))); + } + else if (member is IPropertySymbol prop && prop.IsIndexer) + { + // If they're indexers, compare their signatures. + return baseType.GetMembers(member.Name) + .Any(baseMember => baseMember is IPropertySymbol baseProperty && + _symbolFilter.Include(baseMember) && + (prop.GetMethod.SignatureEquals(baseProperty.GetMethod) || + prop.SetMethod.SignatureEquals(baseProperty.SetMethod))); + } + else + { + // For all other kinds of members, compare their names. + return baseType.GetMembers(member.Name) + .Any(_symbolFilter.Include); + } + } + + private SyntaxNode Visit(SyntaxNode namedTypeNode, INamedTypeSymbol namedType) + { + IEnumerable members = namedType.GetMembers().Where(_symbolFilter.Include); + + // If it's a value type + if (namedType.TypeKind == TypeKind.Struct) + { + namedTypeNode = _syntaxGenerator.AddMembers(namedTypeNode, namedType.SynthesizeDummyFields(_symbolFilter, _attributeDataSymbolFilter)); + } + + namedTypeNode = _syntaxGenerator.AddMembers(namedTypeNode, namedType.TryGetInternalDefaultConstructor(_symbolFilter)); + + foreach (ISymbol member in members.Order()) + { + if (member is IMethodSymbol method) + { + // If the method is ExplicitInterfaceImplementation and is derived from an interface that was filtered out, we must filter it out as well. + if (method.MethodKind == MethodKind.ExplicitInterfaceImplementation && + method.ExplicitInterfaceImplementations.Any(m => !_symbolFilter.Include(m.ContainingSymbol) || + // if explicit interface implementation method has inaccessible type argument + m.ContainingType.HasInaccessibleTypeArgument(_symbolFilter))) + { + continue; + } + + // Filter out default constructors since these will be added automatically + if (_hideImplicitDefaultConstructors && method.IsImplicitDefaultConstructor(_symbolFilter)) + { + continue; + } + } + + // If the property is derived from an interface that was filtered out, we must not filter it out either. + if (member is IPropertySymbol property && !property.ExplicitInterfaceImplementations.IsEmpty && + property.ExplicitInterfaceImplementations.Any(m => !_symbolFilter.Include(m.ContainingSymbol))) + { + continue; + } + + SyntaxNode memberDeclaration = _syntaxGenerator + .DeclarationExt(member, _symbolFilter) + .AddMemberAttributes(_syntaxGenerator, member, _attributeDataSymbolFilter); + + if (member is INamedTypeSymbol nestedTypeSymbol) + { + memberDeclaration = Visit(memberDeclaration, nestedTypeSymbol); + } + + if (HidesBaseMember(member)) + { + DeclarationModifiers mods = _syntaxGenerator.GetModifiers(memberDeclaration); + memberDeclaration = _syntaxGenerator.WithModifiers(memberDeclaration, mods.WithIsNew(isNew: true)); + } + + try + { + namedTypeNode = _syntaxGenerator.AddMembers(namedTypeNode, memberDeclaration); + } + catch (InvalidOperationException e) + { + // re-throw the InvalidOperationException with the symbol that caused it. + throw new InvalidOperationException(string.Format(Resources.AddMemberThrowsException, + member.ToDisplayString(), + namedTypeNode, + e.Message)); + } + } + + return namedTypeNode; + } + + private SyntaxNode GenerateAssemblyAttributes(IAssemblySymbol assembly, SyntaxNode compilationUnit) + { + // When assembly references aren't available, assembly attributes with foreign types won't be resolved. + ImmutableArray attributes = assembly.GetAttributes().ExcludeNonVisibleOutsideOfAssembly(_attributeDataSymbolFilter); + + // Emit assembly attributes from the IAssemblySymbol + List attributeSyntaxNodes = attributes + .Where(attribute => !attribute.IsReserved()) + .Select(attribute => _syntaxGenerator.Attribute(attribute) + .WithTrailingTrivia(SyntaxFactory.LineFeed)) + .ToList(); + + // [assembly: System.Reflection.AssemblyVersion("x.x.x.x")] + if (attributes.All(attribute => attribute.AttributeClass?.ToDisplayString() != typeof(AssemblyVersionAttribute).FullName)) + { + attributeSyntaxNodes.Add(_syntaxGenerator.Attribute(typeof(AssemblyVersionAttribute).FullName!, + SyntaxFactory.AttributeArgument(SyntaxFactory.IdentifierName($"\"{assembly.Identity.Version}\""))) + .WithTrailingTrivia(SyntaxFactory.LineFeed)); + } + + // [assembly: System.Runtime.CompilerServices.ReferenceAssembly] + if (attributes.All(attribute => attribute.AttributeClass?.ToDisplayString() != typeof(ReferenceAssemblyAttribute).FullName)) + { + attributeSyntaxNodes.Add(_syntaxGenerator.Attribute(typeof(ReferenceAssemblyAttribute).FullName!) + .WithTrailingTrivia(SyntaxFactory.LineFeed)); + } + + // [assembly: System.Reflection.AssemblyFlags((System.Reflection.AssemblyNameFlags)0x70)] + if (attributes.All(attribute => attribute.AttributeClass?.ToDisplayString() != typeof(AssemblyFlagsAttribute).FullName)) + { + attributeSyntaxNodes.Add(_syntaxGenerator.Attribute(typeof(AssemblyFlagsAttribute).FullName!, + SyntaxFactory.AttributeArgument(SyntaxFactory.IdentifierName("(System.Reflection.AssemblyNameFlags)0x70"))) + .WithTrailingTrivia(SyntaxFactory.LineFeed)); + } + + return _syntaxGenerator.AddAttributes(compilationUnit, attributeSyntaxNodes); + } + + private SyntaxNode GenerateForwardedTypeAssemblyAttributes(IAssemblySymbol assembly, SyntaxNode compilationUnit) + { + foreach (INamedTypeSymbol symbol in assembly.GetForwardedTypes().Where(_symbolFilter.Include)) + { + if (symbol.TypeKind != TypeKind.Error) + { + // see https://github.com/dotnet/roslyn/issues/67341 + // GetForwardedTypes returns bound generics, but `typeof` requires unbound + TypeSyntax typeSyntaxNode = (TypeSyntax)_syntaxGenerator.TypeExpression(symbol.MakeUnboundIfGeneric()); + compilationUnit = _syntaxGenerator.AddAttributes(compilationUnit, + _syntaxGenerator.Attribute(typeof(TypeForwardedToAttribute).FullName!, + SyntaxFactory.TypeOfExpression(typeSyntaxNode)).WithTrailingTrivia(SyntaxFactory.LineFeed)); + } + else + { + _log.LogWarning(string.Format( + Resources.ResolveTypeForwardFailed, + symbol.ToDisplayString(), + $"{symbol.ContainingAssembly.Name}.dll")); + } + } + + return compilationUnit; + } + + private static IEnumerable EnumerateNamespaces(IAssemblySymbol assemblySymbol) + { + Stack stack = new(); + stack.Push(assemblySymbol.GlobalNamespace); + + while (stack.Count > 0) + { + INamespaceSymbol current = stack.Pop(); + + yield return current; + + foreach (INamespaceSymbol subNamespace in current.GetNamespaceMembers()) + { + stack.Push(subNamespace); + } + } + } + + private OptionSet DefineFormattingOptions() + { + // TODO: consider to move configuration into file. + return _adhocWorkspace.Options + .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInTypes, true) + .WithChangedOption(CSharpFormattingOptions.WrappingKeepStatementsOnSingleLine, true) + .WithChangedOption(CSharpFormattingOptions.WrappingPreserveSingleLine, true) + .WithChangedOption(CSharpFormattingOptions.IndentBlock, false) + .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInMethods, false) + .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInProperties, false) + .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInAccessors, false) + .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInAnonymousMethods, false) + .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInControlBlocks, false) + .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInAnonymousTypes, false) + .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInObjectCollectionArrayInitializers, false) + .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInLambdaExpressionBody, false) + .WithChangedOption(CSharpFormattingOptions.NewLineForMembersInObjectInit, false) + .WithChangedOption(CSharpFormattingOptions.NewLineForMembersInAnonymousTypes, false) + .WithChangedOption(CSharpFormattingOptions.NewLineForClausesInQuery, false); + } +} diff --git a/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/CSharpFileBuilder.cs b/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/CSharpFileBuilder.cs index 0301672ffe3e..a5cfa52b1af5 100644 --- a/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/CSharpFileBuilder.cs +++ b/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/CSharpFileBuilder.cs @@ -1,351 +1,73 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Collections.Immutable; -using System.Diagnostics; -using System.Reflection; -using System.Runtime.CompilerServices; +#if !NET +using System.Text.RegularExpressions; +#endif using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Formatting; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Editing; -using Microsoft.CodeAnalysis.Formatting; -using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.Simplification; using Microsoft.DotNet.ApiSymbolExtensions; using Microsoft.DotNet.ApiSymbolExtensions.Filtering; using Microsoft.DotNet.ApiSymbolExtensions.Logging; -using Microsoft.DotNet.GenAPI.SyntaxRewriter; namespace Microsoft.DotNet.GenAPI { /// /// Processes assembly symbols to build corresponding structures in C# language. /// - public sealed class CSharpFileBuilder : IAssemblySymbolWriter, IDisposable + public sealed class CSharpFileBuilder : IAssemblySymbolWriter { - private readonly ILog _log; private readonly TextWriter _textWriter; - private readonly ISymbolFilter _symbolFilter; - private readonly ISymbolFilter _attributeDataSymbolFilter; - private readonly string? _exceptionMessage; - private readonly bool _includeAssemblyAttributes; - private readonly AdhocWorkspace _adhocWorkspace; - private readonly SyntaxGenerator _syntaxGenerator; - private readonly IEnumerable _metadataReferences; - private readonly bool _addPartialModifier; + private readonly string? _header; + private readonly CSharpAssemblyDocumentGenerator _docGenerator; public CSharpFileBuilder(ILog log, - ISymbolFilter symbolFilter, - ISymbolFilter attributeDataSymbolFilter, - TextWriter textWriter, - string? exceptionMessage, - bool includeAssemblyAttributes, - IEnumerable metadataReferences, - bool addPartialModifier) + TextWriter textWriter, + IAssemblySymbolLoader loader, + ISymbolFilter symbolFilter, + ISymbolFilter attributeDataSymbolFilter, + string? header, + string? exceptionMessage, + bool includeAssemblyAttributes, + IEnumerable? metadataReferences = null, + bool addPartialModifier = true) { - _log = log; _textWriter = textWriter; - _symbolFilter = symbolFilter; - _attributeDataSymbolFilter = attributeDataSymbolFilter; - _exceptionMessage = exceptionMessage; - _includeAssemblyAttributes = includeAssemblyAttributes; - _adhocWorkspace = new AdhocWorkspace(); - _syntaxGenerator = SyntaxGenerator.GetGenerator(_adhocWorkspace, LanguageNames.CSharp); - _metadataReferences = metadataReferences; - _addPartialModifier = addPartialModifier; + _header = header; + _docGenerator = new CSharpAssemblyDocumentGenerator(log, loader, symbolFilter, attributeDataSymbolFilter, exceptionMessage, includeAssemblyAttributes, metadataReferences, addPartialModifier: addPartialModifier); } /// public void WriteAssembly(IAssemblySymbol assemblySymbol) { - CSharpCompilationOptions compilationOptions = new(OutputKind.DynamicallyLinkedLibrary, - nullableContextOptions: NullableContextOptions.Enable); - Project project = _adhocWorkspace.AddProject(ProjectInfo.Create( - ProjectId.CreateNewId(), VersionStamp.Create(), assemblySymbol.Name, assemblySymbol.Name, LanguageNames.CSharp, - compilationOptions: compilationOptions)); - project = project.AddMetadataReferences(_metadataReferences); - - IEnumerable namespaceSymbols = EnumerateNamespaces(assemblySymbol).Where(_symbolFilter.Include); - List namespaceSyntaxNodes = []; - - foreach (INamespaceSymbol namespaceSymbol in namespaceSymbols.Order()) - { - SyntaxNode? syntaxNode = Visit(namespaceSymbol); - - if (syntaxNode is not null) - { - namespaceSyntaxNodes.Add(syntaxNode); - } - } - - SyntaxNode compilationUnit = _syntaxGenerator.CompilationUnit(namespaceSyntaxNodes) - .WithAdditionalAnnotations(Formatter.Annotation, Simplifier.Annotation) - .Rewrite(new TypeDeclarationCSharpSyntaxRewriter(addPartialModifier: true)) - .Rewrite(new BodyBlockCSharpSyntaxRewriter(_exceptionMessage)); - - if (_includeAssemblyAttributes) - { - compilationUnit = GenerateAssemblyAttributes(assemblySymbol, compilationUnit); - } - - compilationUnit = GenerateForwardedTypeAssemblyAttributes(assemblySymbol, compilationUnit); - compilationUnit = compilationUnit.NormalizeWhitespace(eol: Environment.NewLine); - - Document document = project.AddDocument(assemblySymbol.Name, compilationUnit); - document = Simplifier.ReduceAsync(document).Result; - document = Formatter.FormatAsync(document, DefineFormattingOptions()).Result; - - document.GetSyntaxRootAsync().Result! - .Rewrite(new SingleLineStatementCSharpSyntaxRewriter()) - .WriteTo(_textWriter); - } - - private SyntaxNode? Visit(INamespaceSymbol namespaceSymbol) - { - SyntaxNode namespaceNode = _syntaxGenerator.NamespaceDeclaration(namespaceSymbol.ToDisplayString()); - - IEnumerable typeMembers = namespaceSymbol.GetTypeMembers().Where(_symbolFilter.Include); - if (!typeMembers.Any()) - { - return null; - } - - foreach (INamedTypeSymbol typeMember in typeMembers.Order()) - { - SyntaxNode typeDeclaration = _syntaxGenerator - .DeclarationExt(typeMember, _symbolFilter) - .AddMemberAttributes(_syntaxGenerator, typeMember, _attributeDataSymbolFilter); - - typeDeclaration = Visit(typeDeclaration, typeMember); - - namespaceNode = _syntaxGenerator.AddMembers(namespaceNode, typeDeclaration); - } - - return namespaceNode; - } - - // Name hiding through inheritance occurs when classes or structs redeclare names that were inherited from base classes.This type of name hiding takes one of the following forms: - // - A constant, field, property, event, or type introduced in a class or struct hides all base class members with the same name. - // - A method introduced in a class or struct hides all non-method base class members with the same name, and all base class methods with the same signature(§7.6). - // - An indexer introduced in a class or struct hides all base class indexers with the same signature(§7.6) . - private bool HidesBaseMember(ISymbol member) - { - if (member.IsOverride) - { - return false; - } - - if (member.ContainingType.BaseType is not INamedTypeSymbol baseType) - { - return false; - } - - if (member is IMethodSymbol method) - { - if (method.MethodKind == MethodKind.ExplicitInterfaceImplementation) - { - return false; - } - - // If they're methods, compare their names and signatures. - return baseType.GetMembers(member.Name) - .Any(baseMember => _symbolFilter.Include(baseMember) && - (baseMember.Kind != SymbolKind.Method || - method.SignatureEquals((IMethodSymbol)baseMember))); - } - else if (member is IPropertySymbol prop && prop.IsIndexer) - { - // If they're indexers, compare their signatures. - return baseType.GetMembers(member.Name) - .Any(baseMember => baseMember is IPropertySymbol baseProperty && - _symbolFilter.Include(baseMember) && - (prop.GetMethod.SignatureEquals(baseProperty.GetMethod) || - prop.SetMethod.SignatureEquals(baseProperty.SetMethod))); - } - else - { - // For all other kinds of members, compare their names. - return baseType.GetMembers(member.Name) - .Any(_symbolFilter.Include); - } - } - - private SyntaxNode Visit(SyntaxNode namedTypeNode, INamedTypeSymbol namedType) - { - IEnumerable members = namedType.GetMembers().Where(_symbolFilter.Include); - - // If it's a value type - if (namedType.TypeKind == TypeKind.Struct) - { - namedTypeNode = _syntaxGenerator.AddMembers(namedTypeNode, namedType.SynthesizeDummyFields(_symbolFilter, _attributeDataSymbolFilter)); - } - - namedTypeNode = _syntaxGenerator.AddMembers(namedTypeNode, namedType.TryGetInternalDefaultConstructor(_symbolFilter)); - - foreach (ISymbol member in members.Order()) - { - if (member is IMethodSymbol method) - { - // If the method is ExplicitInterfaceImplementation and is derived from an interface that was filtered out, we must filter out it as well. - if (method.MethodKind == MethodKind.ExplicitInterfaceImplementation && - method.ExplicitInterfaceImplementations.Any(m => !_symbolFilter.Include(m.ContainingSymbol) || - // if explicit interface implementation method has inaccessible type argument - m.ContainingType.HasInaccessibleTypeArgument(_symbolFilter))) - { - continue; - } - - // Filter out default constructors since these will be added automatically - if (method.IsImplicitDefaultConstructor(_symbolFilter)) - { - continue; - } - } - - // If the property is derived from an interface that was filter out, we must filtered out it either. - if (member is IPropertySymbol property && !property.ExplicitInterfaceImplementations.IsEmpty && - property.ExplicitInterfaceImplementations.Any(m => !_symbolFilter.Include(m.ContainingSymbol))) - { - continue; - } - - SyntaxNode memberDeclaration = _syntaxGenerator - .DeclarationExt(member, _symbolFilter) - .AddMemberAttributes(_syntaxGenerator, member, _attributeDataSymbolFilter); - - if (member is INamedTypeSymbol nestedTypeSymbol) - { - memberDeclaration = Visit(memberDeclaration, nestedTypeSymbol); - } - - if (HidesBaseMember(member)) - { - DeclarationModifiers mods = _syntaxGenerator.GetModifiers(memberDeclaration); - memberDeclaration = _syntaxGenerator.WithModifiers(memberDeclaration, mods.WithIsNew(isNew: true)); - } - - try - { - namedTypeNode = _syntaxGenerator.AddMembers(namedTypeNode, memberDeclaration); - } - catch (InvalidOperationException e) - { - // re-throw the InvalidOperationException with the symbol that caused it. - throw new InvalidOperationException(string.Format(Resources.AddMemberThrowsException, - member.ToDisplayString(), - namedTypeNode, - e.Message)); - } - } - - return namedTypeNode; + _textWriter.Write(GetFormattedHeader(_header)); + Document document = _docGenerator.GetDocumentForAssembly(assemblySymbol); + _docGenerator.GetFormattedRootNodeForDocument(document).WriteTo(_textWriter); } - private SyntaxNode GenerateAssemblyAttributes(IAssemblySymbol assembly, SyntaxNode compilationUnit) + private static string GetFormattedHeader(string? customHeader) { - // When assembly references aren't available, assembly attributes with foreign types won't be resolved. - ImmutableArray attributes = assembly.GetAttributes().ExcludeNonVisibleOutsideOfAssembly(_attributeDataSymbolFilter); + const string defaultFileHeader = """ + //------------------------------------------------------------------------------ + // + // This code was generated by a tool. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ - // Emit assembly attributes from the IAssemblySymbol - List attributeSyntaxNodes = attributes - .Where(attribute => !attribute.IsReserved()) - .Select(attribute => _syntaxGenerator.Attribute(attribute) - .WithTrailingTrivia(SyntaxFactory.LineFeed)) - .ToList(); + """; - // [assembly: System.Reflection.AssemblyVersion("x.x.x.x")] - if (attributes.All(attribute => attribute.AttributeClass?.ToDisplayString() != typeof(AssemblyVersionAttribute).FullName)) + if (customHeader != null) { - attributeSyntaxNodes.Add(_syntaxGenerator.Attribute(typeof(AssemblyVersionAttribute).FullName!, - SyntaxFactory.AttributeArgument(SyntaxFactory.IdentifierName($"\"{assembly.Identity.Version}\""))) - .WithTrailingTrivia(SyntaxFactory.LineFeed)); +#if NET + return customHeader.ReplaceLineEndings(); +#else + return Regex.Replace(customHeader, @"\r\n|\n\r|\n|\r", Environment.NewLine); +#endif } - // [assembly: System.Runtime.CompilerServices.ReferenceAssembly] - if (attributes.All(attribute => attribute.AttributeClass?.ToDisplayString() != typeof(ReferenceAssemblyAttribute).FullName)) - { - attributeSyntaxNodes.Add(_syntaxGenerator.Attribute(typeof(ReferenceAssemblyAttribute).FullName!) - .WithTrailingTrivia(SyntaxFactory.LineFeed)); - } - - // [assembly: System.Reflection.AssemblyFlags((System.Reflection.AssemblyNameFlags)0x70)] - if (attributes.All(attribute => attribute.AttributeClass?.ToDisplayString() != typeof(AssemblyFlagsAttribute).FullName)) - { - attributeSyntaxNodes.Add(_syntaxGenerator.Attribute(typeof(AssemblyFlagsAttribute).FullName!, - SyntaxFactory.AttributeArgument(SyntaxFactory.IdentifierName("(System.Reflection.AssemblyNameFlags)0x70"))) - .WithTrailingTrivia(SyntaxFactory.LineFeed)); - } - - return _syntaxGenerator.AddAttributes(compilationUnit, attributeSyntaxNodes); - } - - private SyntaxNode GenerateForwardedTypeAssemblyAttributes(IAssemblySymbol assembly, SyntaxNode compilationUnit) - { - foreach (INamedTypeSymbol symbol in assembly.GetForwardedTypes().Where(_symbolFilter.Include)) - { - if (symbol.TypeKind != TypeKind.Error) - { - // see https://github.com/dotnet/roslyn/issues/67341 - // GetForwardedTypes returns bound generics, but `typeof` requires unbound - TypeSyntax typeSyntaxNode = (TypeSyntax)_syntaxGenerator.TypeExpression(symbol.MakeUnboundIfGeneric()); - compilationUnit = _syntaxGenerator.AddAttributes(compilationUnit, - _syntaxGenerator.Attribute(typeof(TypeForwardedToAttribute).FullName!, - SyntaxFactory.TypeOfExpression(typeSyntaxNode)).WithTrailingTrivia(SyntaxFactory.LineFeed)); - } - else - { - _log.LogWarning(string.Format( - Resources.ResolveTypeForwardFailed, - symbol.ToDisplayString(), - $"{symbol.ContainingAssembly.Name}.dll")); - } - } - - return compilationUnit; - } - - private static IEnumerable EnumerateNamespaces(IAssemblySymbol assemblySymbol) - { - Stack stack = new(); - stack.Push(assemblySymbol.GlobalNamespace); - - while (stack.Count > 0) - { - INamespaceSymbol current = stack.Pop(); - - yield return current; - - foreach (INamespaceSymbol subNamespace in current.GetNamespaceMembers()) - { - stack.Push(subNamespace); - } - } + return defaultFileHeader; } - - private OptionSet DefineFormattingOptions() - { - // TODO: consider to move configuration into file. - return _adhocWorkspace.Options - .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInTypes, true) - .WithChangedOption(CSharpFormattingOptions.WrappingKeepStatementsOnSingleLine, true) - .WithChangedOption(CSharpFormattingOptions.WrappingPreserveSingleLine, true) - .WithChangedOption(CSharpFormattingOptions.IndentBlock, false) - .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInMethods, false) - .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInProperties, false) - .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInAccessors, false) - .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInAnonymousMethods, false) - .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInControlBlocks, false) - .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInAnonymousTypes, false) - .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInObjectCollectionArrayInitializers, false) - .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInLambdaExpressionBody, false) - .WithChangedOption(CSharpFormattingOptions.NewLineForMembersInObjectInit, false) - .WithChangedOption(CSharpFormattingOptions.NewLineForMembersInAnonymousTypes, false) - .WithChangedOption(CSharpFormattingOptions.NewLineForClausesInQuery, false); - } - - /// - public void Dispose() => _textWriter.Dispose(); } } diff --git a/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/GenAPIApp.cs b/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/GenAPIApp.cs index f537d26e823b..d34c1e6366bc 100644 --- a/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/GenAPIApp.cs +++ b/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/GenAPIApp.cs @@ -18,11 +18,11 @@ namespace Microsoft.DotNet.GenAPI public static class GenAPIApp { /// - /// Initialize and run Roslyn-based GenAPI tool. + /// Initialize and run Roslyn-based GenAPI tool specifying the assemblies to load. /// public static void Run(ILog log, - string[] assemblies, - string[]? assemblyReferences, + string[] assembliesPaths, + string[]? assemblyReferencesPaths, string? outputPath, string? headerFile, string? exceptionMessage, @@ -31,59 +31,68 @@ public static void Run(ILog log, bool respectInternals, bool includeAssemblyAttributes) { - bool resolveAssemblyReferences = assemblyReferences?.Length > 0; - - // Create, configure and execute the assembly loader. - AssemblySymbolLoader loader = new(log, resolveAssemblyReferences, respectInternals); - if (assemblyReferences is not null) - { - loader.AddReferenceSearchPaths(assemblyReferences); - } - IReadOnlyList assemblySymbols = loader.LoadAssemblies(assemblies); - - string headerFileText = ReadHeaderFile(headerFile); + (IAssemblySymbolLoader loader, Dictionary assemblySymbols) = AssemblySymbolLoader.CreateFromFiles( + log, + assembliesPaths, + assemblyReferencesPaths, + respectInternals: respectInternals); + + Run(log, + loader, + assemblySymbols, + outputPath, + headerFile, + exceptionMessage, + excludeApiFiles, + excludeAttributesFiles, + respectInternals, + includeAssemblyAttributes); + } + /// + /// Initialize and run Roslyn-based GenAPI tool using an assembly symbol loader that pre-loaded the assemblies separately. + /// + public static void Run(ILog log, + IAssemblySymbolLoader loader, + Dictionary assemblySymbols, + string? outputPath, + string? headerFile, + string? exceptionMessage, + string[]? excludeApiFiles, + string[]? excludeAttributesFiles, + bool respectInternals, + bool includeAssemblyAttributes) + { + // Shared accessibility filter for the API and Attribute composite filters. AccessibilitySymbolFilter accessibilitySymbolFilter = new( respectInternals, includeEffectivelyPrivateSymbols: true, includeExplicitInterfaceImplementationSymbols: true); - // Configure the symbol filter - CompositeSymbolFilter symbolFilter = new(); - if (excludeApiFiles is not null) - { - symbolFilter.Add(new DocIdSymbolFilter(excludeApiFiles)); - } - symbolFilter.Add(new ImplicitSymbolFilter()); - symbolFilter.Add(accessibilitySymbolFilter); - - // Configure the attribute data symbol filter - CompositeSymbolFilter attributeDataSymbolFilter = new(); - if (excludeAttributesFiles is not null) - { - attributeDataSymbolFilter.Add(new DocIdSymbolFilter(excludeAttributesFiles)); - } - attributeDataSymbolFilter.Add(accessibilitySymbolFilter); - // Invoke the CSharpFileBuilder for each directly loaded assembly. - foreach (IAssemblySymbol? assemblySymbol in assemblySymbols) + foreach (KeyValuePair kvp in assemblySymbols) { - if (assemblySymbol is null) - continue; + using TextWriter textWriter = GetTextWriter(outputPath, kvp.Key); - using TextWriter textWriter = GetTextWriter(outputPath, assemblySymbol.Name); - textWriter.Write(headerFileText); + ISymbolFilter symbolFilter = SymbolFilterFactory.GetFilterFromFiles( + excludeApiFiles, accessibilitySymbolFilter, + respectInternals: respectInternals); + ISymbolFilter attributeDataSymbolFilter = SymbolFilterFactory.GetFilterFromFiles( + excludeAttributesFiles, accessibilitySymbolFilter, + respectInternals: respectInternals); - using CSharpFileBuilder fileBuilder = new(log, + CSharpFileBuilder fileBuilder = new(log, + textWriter, + loader, symbolFilter, attributeDataSymbolFilter, - textWriter, + headerFile, exceptionMessage, includeAssemblyAttributes, loader.MetadataReferences, addPartialModifier: true); - fileBuilder.WriteAssembly(assemblySymbol); + fileBuilder.WriteAssembly(kvp.Value); } } @@ -103,33 +112,5 @@ private static TextWriter GetTextWriter(string? outputDirPath, string assemblyNa return File.CreateText(outputDirPath); } - - // Read the header file if specified, or use default one. - private static string ReadHeaderFile(string? headerFile) - { - const string defaultFileHeader = """ - //------------------------------------------------------------------------------ - // - // This code was generated by a tool. - // - // Changes to this file may cause incorrect behavior and will be lost if - // the code is regenerated. - // - //------------------------------------------------------------------------------ - - """; - - string header = !string.IsNullOrEmpty(headerFile) ? - File.ReadAllText(headerFile) : - defaultFileHeader; - -#if NET - header = header.ReplaceLineEndings(); -#else - header = Regex.Replace(header, @"\r\n|\n\r|\n|\r", Environment.NewLine); -#endif - - return header; - } } } diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/AssemblySymbolLoader.cs b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/AssemblySymbolLoader.cs index f90efb19f4ad..caf4300aac15 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/AssemblySymbolLoader.cs +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/AssemblySymbolLoader.cs @@ -51,18 +51,66 @@ public class AssemblySymbolLoader : IAssemblySymbolLoader /// public const string AssemblyReferenceNotFoundErrorCode = "CP1002"; + /// + /// Creates an assembly symbol loader and its corresponding assembly symbols from the given DLL files in the filesystem. + /// + /// The logger instance to use for message logging. + /// A collection of paths where the assembly DLLs should be searched. + /// An optional collection of paths where the assembly references should be searched. + /// An optional list of diagnostic options to use when compiling the loaded assemblies. + /// Whether to include internal symbols or not. + /// A tuple containing an assembly symbol loader and its corresponding dictionary of assembly symbols. + public static (AssemblySymbolLoader, Dictionary) CreateFromFiles(ILog log, string[] assembliesPaths, string[]? assemblyReferencesPaths, IEnumerable>? diagnosticOptions = null, bool respectInternals = false) + { + if (assembliesPaths.Length == 0) + { + return (new AssemblySymbolLoader(log, diagnosticOptions, resolveAssemblyReferences: true, includeInternalSymbols: respectInternals), + new Dictionary()); + } + + bool atLeastOneReferencePath = assemblyReferencesPaths?.Count() > 0; + AssemblySymbolLoader loader = new(log, diagnosticOptions, resolveAssemblyReferences: atLeastOneReferencePath, includeInternalSymbols: respectInternals); + if (atLeastOneReferencePath) + { + loader.AddReferenceSearchPaths(assemblyReferencesPaths!); + } + + // First resolve all assemblies that are passed in and create metadata references out of them. + // Reference assemblies of the passed in assemblies that themselves are passed in, will be skipped to be resolved, + // as they are resolved as part of the loop below. + ImmutableHashSet fileNames = assembliesPaths.Select(path => Path.GetFileName(path)).ToImmutableHashSet(); + List assembliesToReturn = loader.LoadFromPaths(assembliesPaths, fileNames); + + // Create IAssemblySymbols out of the MetadataReferences. + // Doing this after resolving references to make sure that references are available. + Dictionary dictionary = []; + foreach (MetadataReference metadataReference in assembliesToReturn) + { + if (loader._cSharpCompilation.GetAssemblyOrModuleSymbol(metadataReference) is IAssemblySymbol assemblySymbol) + { + dictionary.Add(assemblySymbol.Name, assemblySymbol); + } + } + + return (loader, dictionary); + } + /// /// Creates a new instance of the class. /// /// A logger instance for logging message. + /// An optional list of diagnostic options to use when compiling the loaded assemblies. /// True to attempt to load references for loaded assemblies from the locations specified with . Default is false. /// True to include all internal metadata for assemblies loaded. Default is false which only includes public and some internal metadata. - public AssemblySymbolLoader(ILog log, bool resolveAssemblyReferences = false, bool includeInternalSymbols = false) + public AssemblySymbolLoader(ILog log, IEnumerable>? diagnosticOptions = null, bool resolveAssemblyReferences = false, bool includeInternalSymbols = false) { _log = log; _loadedAssemblies = []; - CSharpCompilationOptions compilationOptions = new(OutputKind.DynamicallyLinkedLibrary, nullableContextOptions: NullableContextOptions.Enable, - metadataImportOptions: includeInternalSymbols ? MetadataImportOptions.Internal : MetadataImportOptions.Public); + CSharpCompilationOptions compilationOptions = new( + OutputKind.DynamicallyLinkedLibrary, + nullableContextOptions: NullableContextOptions.Enable, + metadataImportOptions: includeInternalSymbols ? MetadataImportOptions.Internal : MetadataImportOptions.Public, + specificDiagnosticOptions: diagnosticOptions); _cSharpCompilation = CSharpCompilation.Create($"AssemblyLoader_{DateTime.Now:MM_dd_yy_HH_mm_ss_FFF}", options: compilationOptions); _resolveReferences = resolveAssemblyReferences; } @@ -95,6 +143,8 @@ public void AddReferenceSearchPaths(params string[] paths) /// public IReadOnlyList LoadAssemblies(params string[] paths) { + _log.LogMessage(MessageImportance.Low, string.Format(Resources.LoadingAssemblies, string.Join(", ", paths))); + // First resolve all assemblies that are passed in and create metadata references out of them. // Reference assemblies of the passed in assemblies that themselves are passed in, will be skipped to be resolved, // as they are resolved as part of the loop below. @@ -119,6 +169,8 @@ public void AddReferenceSearchPaths(params string[] paths) /// public IReadOnlyList LoadAssembliesFromArchive(string archivePath, IReadOnlyList relativePaths) { + _log.LogMessage(MessageImportance.Low, string.Format(Resources.LoadingAssembliesFromArchive, string.Join(", ", relativePaths), archivePath)); + using FileStream stream = File.OpenRead(archivePath); using ZipArchive zipFile = new(stream); @@ -144,7 +196,8 @@ public void AddReferenceSearchPaths(params string[] paths) string name = Path.GetFileName(relativePaths[i]); if (!_loadedAssemblies.TryGetValue(name, out MetadataReference? metadataReference)) { - metadataReference = CreateAndAddReferenceToCompilation(name, memoryStream, fileNames); + string rootAssemblyDisplayString = string.Format(Resources.RootAssemblyFromPackageDisplayString, relativePaths[i], archivePath); + metadataReference = CreateAndAddReferenceToCompilation(name, rootAssemblyDisplayString, memoryStream, fileNames); } metadataReferences[i] = metadataReference; @@ -170,6 +223,8 @@ public void AddReferenceSearchPaths(params string[] paths) /// public IAssemblySymbol? LoadAssembly(string path) { + _log.LogMessage(MessageImportance.Low, string.Format(Resources.LoadingAssembly, path)); + MetadataReference metadataReference = CreateOrGetMetadataReferenceFromPath(path); IAssemblySymbol? assemblySymbol = _cSharpCompilation.GetAssemblyOrModuleSymbol(metadataReference) as IAssemblySymbol; LogCompilationDiagnostics(); @@ -180,6 +235,8 @@ public void AddReferenceSearchPaths(params string[] paths) /// public IAssemblySymbol? LoadAssembly(string name, Stream stream) { + _log.LogMessage(MessageImportance.Low, string.Format(Resources.LoadingAssemblyFromStream, name)); + if (stream.Position >= stream.Length) { throw new ArgumentException(Resources.StreamPositionGreaterThanLength, nameof(stream)); @@ -187,7 +244,8 @@ public void AddReferenceSearchPaths(params string[] paths) if (!_loadedAssemblies.TryGetValue(name, out MetadataReference? metadataReference)) { - metadataReference = CreateAndAddReferenceToCompilation(name, stream); + string rootAssemblyDisplayString = string.Format(Resources.RootAssemblyDisplayString, name); + metadataReference = CreateAndAddReferenceToCompilation(name, rootAssemblyDisplayString, stream); } IAssemblySymbol? assemblySymbol = _cSharpCompilation.GetAssemblyOrModuleSymbol(metadataReference) as IAssemblySymbol; @@ -318,13 +376,14 @@ private MetadataReference CreateOrGetMetadataReferenceFromPath(string path, Immu if (!_loadedAssemblies.TryGetValue(name, out MetadataReference? metadataReference)) { using FileStream stream = File.OpenRead(path); - metadataReference = CreateAndAddReferenceToCompilation(name, stream, referenceAssemblyNamesToIgnore); + string rootAssemblyDisplayString = string.Format(Resources.RootAssemblyDisplayString, path); + metadataReference = CreateAndAddReferenceToCompilation(name, rootAssemblyDisplayString, stream, referenceAssemblyNamesToIgnore); } return metadataReference; } - private MetadataReference CreateAndAddReferenceToCompilation(string name, Stream fileStream, ImmutableHashSet? referenceAssemblyNamesToIgnore = null) + private MetadataReference CreateAndAddReferenceToCompilation(string assemblyName, string rootAssemblyDisplayString, Stream fileStream, ImmutableHashSet? referenceAssemblyNamesToIgnore = null, string? referenceeAssemblyName = null) { // If we need to resolve references we can't reuse the same stream after creating the metadata // reference from it as Roslyn closes it. So instead we use PEReader and get the bytes @@ -333,51 +392,60 @@ private MetadataReference CreateAndAddReferenceToCompilation(string name, Stream if (!reader.HasMetadata) { - throw new ArgumentException(string.Format(Resources.ProvidedStreamDoesNotHaveMetadata, name)); + throw new ArgumentException(string.Format(Resources.ProvidedStreamDoesNotHaveMetadata, assemblyName)); } PEMemoryBlock image = reader.GetEntireImage(); MetadataReference metadataReference = MetadataReference.CreateFromImage(image.GetContent()); - _loadedAssemblies.Add(name, metadataReference); + _loadedAssemblies.Add(assemblyName, metadataReference); _cSharpCompilation = _cSharpCompilation.AddReferences([ metadataReference ]); + if (referenceeAssemblyName is null) + { + _log.LogMessage(MessageImportance.Low, string.Format(Resources.AssemblyLoaded, assemblyName)); + } + else + { + _log.LogMessage(MessageImportance.Low, string.Format(Resources.AssemblyReferenceLoaded, assemblyName, referenceeAssemblyName)); + } + if (_resolveReferences) { - ResolveReferences(reader, referenceAssemblyNamesToIgnore); + ResolveReferences(reader, assemblyName, rootAssemblyDisplayString, referenceAssemblyNamesToIgnore); } return metadataReference; } - private void ResolveReferences(PEReader peReader, ImmutableHashSet? referenceAssemblyNamesToIgnore = null) + private void ResolveReferences(PEReader peReader, string assemblyName, string rootAssemblyDisplayString, ImmutableHashSet? referenceAssemblyNamesToIgnore = null) { MetadataReader reader = peReader.GetMetadataReader(); - foreach (AssemblyReferenceHandle handle in reader.AssemblyReferences) + foreach (AssemblyReferenceHandle assemblyReferenceHandle in reader.AssemblyReferences) { - AssemblyReference reference = reader.GetAssemblyReference(handle); - string nameWithoutExtension = reader.GetString(reference.Name); + AssemblyReference assemblyReference = reader.GetAssemblyReference(assemblyReferenceHandle); + string assemblyReferenceNameWithoutExtension = reader.GetString(assemblyReference.Name); // Skip assemblies that should never get loaded because they are purely internal - if (s_assembliesToIgnore.Contains(nameWithoutExtension)) + if (s_assembliesToIgnore.Contains(assemblyReferenceNameWithoutExtension)) continue; - string name = nameWithoutExtension + ".dll"; + string assemblyReferenceName = assemblyReferenceNameWithoutExtension + ".dll"; // Skip reference assemblies that are loaded later. - if (referenceAssemblyNamesToIgnore != null && referenceAssemblyNamesToIgnore.Contains(name)) + if (referenceAssemblyNamesToIgnore != null && referenceAssemblyNamesToIgnore.Contains(assemblyReferenceName)) continue; // If the assembly reference is already loaded, don't do anything. - if (_loadedAssemblies.ContainsKey(name)) + if (_loadedAssemblies.ContainsKey(assemblyReferenceName)) continue; // First we try to see if a reference path for this specific assembly was passed in directly, and if so // we use that. - if (_referencePathFiles.TryGetValue(name, out string? fullReferencePath)) + if (_referencePathFiles.TryGetValue(assemblyReferenceName, out string? fullReferencePath)) { // TODO: add version check and add a warning if it doesn't match? - using FileStream resolvedStream = File.OpenRead(Path.Combine(fullReferencePath, name)); - CreateAndAddReferenceToCompilation(name, resolvedStream, referenceAssemblyNamesToIgnore); + using FileStream resolvedStream = File.OpenRead(Path.Combine(fullReferencePath, assemblyReferenceName)); + CreateAndAddReferenceToCompilation(assemblyReferenceName, rootAssemblyDisplayString, resolvedStream, referenceAssemblyNamesToIgnore, assemblyName); } // If we can't find a specific reference path for the dependency, then we look in the folders where the // rest of the reference paths are located to see if we can find the dependency there. @@ -387,12 +455,12 @@ private void ResolveReferences(PEReader peReader, ImmutableHashSet? refe foreach (string referencePathDirectory in _referencePathDirectories) { - string potentialPath = Path.Combine(referencePathDirectory, name); + string potentialPath = Path.Combine(referencePathDirectory, assemblyReferenceName); if (File.Exists(potentialPath)) { // TODO: add version check and add a warning if it doesn't match? using FileStream resolvedStream = File.OpenRead(potentialPath); - CreateAndAddReferenceToCompilation(name, resolvedStream, referenceAssemblyNamesToIgnore); + CreateAndAddReferenceToCompilation(assemblyReferenceName, rootAssemblyDisplayString, resolvedStream, referenceAssemblyNamesToIgnore, assemblyName); found = true; break; } @@ -400,7 +468,10 @@ private void ResolveReferences(PEReader peReader, ImmutableHashSet? refe if (!found) { - _log.LogWarning(AssemblyReferenceNotFoundErrorCode, string.Format(Resources.CouldNotResolveReference, name)); + // Temporarily downgrade assembly reference load warnings to messages: https://github.com/dotnet/sdk/issues/46236 + // _log.LogWarning(AssemblyReferenceNotFoundErrorCode, + // string.Format(Resources.CouldNotResolveReference, assemblyReferenceName, rootAssemblyDisplayString)); + _log.LogMessage(MessageImportance.High, string.Format(Resources.CouldNotResolveReference, assemblyReferenceName, rootAssemblyDisplayString)); } } } diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/AssemblySymbolLoaderFactory.cs b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/AssemblySymbolLoaderFactory.cs index 5a2b74600cc0..e5448223b273 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/AssemblySymbolLoaderFactory.cs +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/AssemblySymbolLoaderFactory.cs @@ -14,6 +14,6 @@ public sealed class AssemblySymbolLoaderFactory(ILog log, bool includeInternalSy { /// public IAssemblySymbolLoader Create(bool shouldResolveReferences) => - new AssemblySymbolLoader(log, shouldResolveReferences, includeInternalSymbols); + new AssemblySymbolLoader(log, resolveAssemblyReferences: shouldResolveReferences, includeInternalSymbols: includeInternalSymbols); } } diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/Filtering/DocIdSymbolFilter.cs b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/Filtering/DocIdSymbolFilter.cs index 3bb8ba16fac6..9bd20dd20b6d 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/Filtering/DocIdSymbolFilter.cs +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/Filtering/DocIdSymbolFilter.cs @@ -9,9 +9,46 @@ namespace Microsoft.DotNet.ApiSymbolExtensions.Filtering /// Implements the logic of filtering out api. /// Reads the file with the list of attributes, types, members in DocId format. /// - public class DocIdSymbolFilter(string[] docIdsToExcludeFiles) : ISymbolFilter + public class DocIdSymbolFilter : ISymbolFilter { - private readonly HashSet _docIdsToExclude = new(ReadDocIdsAttributes(docIdsToExcludeFiles)); + private readonly HashSet _docIdsToExclude; + + /// + /// Creates a filter to exclude APIs using the DocIDs provided in the specified files. + /// + /// A collection of files each containing multiple DocIDs to exclude. + /// An instance of the symbol filter. + public static DocIdSymbolFilter CreateFromFiles(params string[] filesWithDocIdsToExclude) + { + List docIds = new(); + + foreach (string docIdsToExcludeFile in filesWithDocIdsToExclude) + { + if (string.IsNullOrWhiteSpace(docIdsToExcludeFile)) + { + continue; + } + + foreach (string docId in ReadDocIdsFromList(File.ReadAllLines(docIdsToExcludeFile))) + { + docIds.Add(docId); + } + } + + return new DocIdSymbolFilter(docIds); + } + + /// + /// Creates a filter to exclude APIs using the DocIDs provided in the specified list. + /// + /// A collection of DocIDs to exclude. + /// An instance of the symbol filter. + public static DocIdSymbolFilter CreateFromLists(params string[] docIdsToExclude) + => new DocIdSymbolFilter(ReadDocIdsFromList(docIdsToExclude)); + + // Private constructor to avoid creating an instance with an empty list. + private DocIdSymbolFilter(IEnumerable docIdsToExclude) + => _docIdsToExclude = [.. docIdsToExclude]; /// /// Determines whether the should be included. @@ -29,20 +66,17 @@ public bool Include(ISymbol symbol) return true; } - private static IEnumerable ReadDocIdsAttributes(IEnumerable docIdsToExcludeFiles) + private static IEnumerable ReadDocIdsFromList(params string[] ids) { - foreach (string docIdsToExcludeFile in docIdsToExcludeFiles) + foreach (string id in ids) { - foreach (string id in File.ReadAllLines(docIdsToExcludeFile)) - { #if NET - if (!string.IsNullOrWhiteSpace(id) && !id.StartsWith('#') && !id.StartsWith("//")) + if (!string.IsNullOrWhiteSpace(id) && !id.StartsWith('#') && !id.StartsWith("//")) #else - if (!string.IsNullOrWhiteSpace(id) && !id.StartsWith("#") && !id.StartsWith("//")) + if (!string.IsNullOrWhiteSpace(id) && !id.StartsWith("#") && !id.StartsWith("//")) #endif - { - yield return id.Trim(); - } + { + yield return id.Trim(); } } } diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/Filtering/SymbolFilterFactory.cs b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/Filtering/SymbolFilterFactory.cs new file mode 100644 index 000000000000..18ea253e5368 --- /dev/null +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/Filtering/SymbolFilterFactory.cs @@ -0,0 +1,88 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; + +namespace Microsoft.DotNet.ApiSymbolExtensions.Filtering; + +/// +/// A factory class to create symbol filters. +/// +public static class SymbolFilterFactory +{ + /// + /// Creates a composite filter to exclude APIs using the DocIDs provided in the specifed file paths. + /// + /// A collection of paths where the exclusion files should be searched. + /// An optional custom accessibility symbol filter to use. + /// Whether to include internal symbols or not. + /// Whether to include effectively private symbols or not. + /// Whether to include explicit interface implementation symbols or not. + /// Whether to include implicit symbols or not. + /// An instance of the symbol filter. + public static ISymbolFilter GetFilterFromFiles(string[]? apiExclusionFilePaths, + AccessibilitySymbolFilter? accessibilitySymbolFilter = null, + bool respectInternals = false, + bool includeEffectivelyPrivateSymbols = true, + bool includeExplicitInterfaceImplementationSymbols = true, + bool includeImplicitSymbolFilter = true) + { + DocIdSymbolFilter? docIdSymbolFilter = + apiExclusionFilePaths?.Length > 0 ? + DocIdSymbolFilter.CreateFromFiles(apiExclusionFilePaths) : null; + + return GetCompositeSymbolFilter(docIdSymbolFilter, accessibilitySymbolFilter, respectInternals, includeEffectivelyPrivateSymbols, includeExplicitInterfaceImplementationSymbols, includeImplicitSymbolFilter); + } + + /// + /// Creates a composite filter to exclude APIs using the DocIDs provided in the specifed list. + /// + /// A collection of exclusion list. + /// An optional custom accessibility symbol filter to use. + /// Whether to include internal symbols or not. + /// Whether to include effectively private symbols or not. + /// Whether to include explicit interface implementation symbols or not. + /// Whether to include implicit symbols or not. + /// An instance of the symbol filter. + public static ISymbolFilter GetFilterFromList(string[]? apiExclusionList, + AccessibilitySymbolFilter? accessibilitySymbolFilter = null, + bool respectInternals = false, + bool includeEffectivelyPrivateSymbols = true, + bool includeExplicitInterfaceImplementationSymbols = true, + bool includeImplicitSymbolFilter = true) + { + DocIdSymbolFilter? docIdSymbolFilter = + apiExclusionList?.Count() > 0 ? + DocIdSymbolFilter.CreateFromLists(apiExclusionList) : null; + + return GetCompositeSymbolFilter(docIdSymbolFilter, accessibilitySymbolFilter, respectInternals, includeEffectivelyPrivateSymbols, includeExplicitInterfaceImplementationSymbols, includeImplicitSymbolFilter); + } + + private static ISymbolFilter GetCompositeSymbolFilter(DocIdSymbolFilter? customFilter, + AccessibilitySymbolFilter? accessibilitySymbolFilter, + bool respectInternals, + bool includeEffectivelyPrivateSymbols, + bool includeExplicitInterfaceImplementationSymbols, + bool includeImplicitSymbolFilter) + { + accessibilitySymbolFilter ??= new( + respectInternals, + includeEffectivelyPrivateSymbols, + includeExplicitInterfaceImplementationSymbols); + + CompositeSymbolFilter filter = new(); + + if (customFilter != null) + { + filter.Add(customFilter); + } + if (includeImplicitSymbolFilter) + { + filter.Add(new ImplicitSymbolFilter()); + } + + filter.Add(accessibilitySymbolFilter); + + return filter; + } +} diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/Resources.resx b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/Resources.resx index d7fa05dbf47f..3b7c96ac9169 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/Resources.resx +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/Resources.resx @@ -117,8 +117,26 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Assembly '{0}' loaded. + + + Assembly '{0}' referenced by '{1}' loaded. + - Could not resolve reference '{0}' in any of the provided search directories. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + + + Loading assemblies '{0}'. + + + Loading assemblies '{0}' ({1}). + + + Loading assembly '{0}'. + + + Loading assembly '{0}' from stream. Could not find matching assembly: '{0}' in any of the search directories. @@ -129,6 +147,12 @@ Provided stream for assembly '{0}' doesn't have any metadata to read. from. + + '{0}' + + + '{0}' ({1}) + Should not be null and contain at least one element. diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.cs.xlf b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.cs.xlf index 324c9c461f20..d1c7c7404f5f 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.cs.xlf +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.cs.xlf @@ -2,9 +2,39 @@ + + Assembly '{0}' loaded. + Assembly '{0}' loaded. + + + + Assembly '{0}' referenced by '{1}' loaded. + Assembly '{0}' referenced by '{1}' loaded. + + - Could not resolve reference '{0}' in any of the provided search directories. - V žádném z uvedených adresářů vyhledávání se nepovedlo přeložit odkaz {0}. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + + + + Loading assemblies '{0}'. + Loading assemblies '{0}'. + + + + Loading assemblies '{0}' ({1}). + Loading assemblies '{0}' ({1}). + + + + Loading assembly '{0}'. + Loading assembly '{0}'. + + + + Loading assembly '{0}' from stream. + Loading assembly '{0}' from stream. @@ -22,6 +52,16 @@ Poskytnutý datový proud pro sestavení {0} nemá žádná metadata pro čtení. + + '{0}' + '{0}' + + + + '{0}' ({1}) + '{0}' ({1}) + + Should not be null and contain at least one element. Nesmí být null a obsahovat alespoň jeden element. diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.de.xlf b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.de.xlf index b1adc5cbceef..a93cc3476f27 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.de.xlf +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.de.xlf @@ -2,9 +2,39 @@ + + Assembly '{0}' loaded. + Assembly '{0}' loaded. + + + + Assembly '{0}' referenced by '{1}' loaded. + Assembly '{0}' referenced by '{1}' loaded. + + - Could not resolve reference '{0}' in any of the provided search directories. - Der Verweis "{0}" konnte in keinem der angegebenen Suchverzeichnisse aufgelöst werden. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + + + + Loading assemblies '{0}'. + Loading assemblies '{0}'. + + + + Loading assemblies '{0}' ({1}). + Loading assemblies '{0}' ({1}). + + + + Loading assembly '{0}'. + Loading assembly '{0}'. + + + + Loading assembly '{0}' from stream. + Loading assembly '{0}' from stream. @@ -22,6 +52,16 @@ Der angegebene Datenstrom für die Assembly "{0}" enthält keine Metadaten, aus denen gelesen werden kann. + + '{0}' + '{0}' + + + + '{0}' ({1}) + '{0}' ({1}) + + Should not be null and contain at least one element. Darf nicht NULL sein und muss mindestens ein Element enthalten. diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.es.xlf b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.es.xlf index 42b08421cccc..2a50d71c6dec 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.es.xlf +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.es.xlf @@ -2,9 +2,39 @@ + + Assembly '{0}' loaded. + Assembly '{0}' loaded. + + + + Assembly '{0}' referenced by '{1}' loaded. + Assembly '{0}' referenced by '{1}' loaded. + + - Could not resolve reference '{0}' in any of the provided search directories. - No se pudo resolver la referencia "{0}" en ninguno de los directorios de búsqueda proporcionados. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + + + + Loading assemblies '{0}'. + Loading assemblies '{0}'. + + + + Loading assemblies '{0}' ({1}). + Loading assemblies '{0}' ({1}). + + + + Loading assembly '{0}'. + Loading assembly '{0}'. + + + + Loading assembly '{0}' from stream. + Loading assembly '{0}' from stream. @@ -22,6 +52,16 @@ La secuencia proporcionada para el ensamblado "{0}" no tiene metadatos que leer. + + '{0}' + '{0}' + + + + '{0}' ({1}) + '{0}' ({1}) + + Should not be null and contain at least one element. No debe ser nulo y debe contener al menos un elemento. diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.fr.xlf b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.fr.xlf index ac4050130c1f..081bfef494a5 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.fr.xlf +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.fr.xlf @@ -2,9 +2,39 @@ + + Assembly '{0}' loaded. + Assembly '{0}' loaded. + + + + Assembly '{0}' referenced by '{1}' loaded. + Assembly '{0}' referenced by '{1}' loaded. + + - Could not resolve reference '{0}' in any of the provided search directories. - Impossible de résoudre la référence «{0}» dans l’un des répertoires de recherche fournis. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + + + + Loading assemblies '{0}'. + Loading assemblies '{0}'. + + + + Loading assemblies '{0}' ({1}). + Loading assemblies '{0}' ({1}). + + + + Loading assembly '{0}'. + Loading assembly '{0}'. + + + + Loading assembly '{0}' from stream. + Loading assembly '{0}' from stream. @@ -22,6 +52,16 @@ Le flux fourni pour l’assembly '{0}' n’a aucune métadonnée à lire. De. + + '{0}' + '{0}' + + + + '{0}' ({1}) + '{0}' ({1}) + + Should not be null and contain at least one element. Ne doit pas être null et contenir au moins un élément. diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.it.xlf b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.it.xlf index c5579a2600b7..7a4ec8b1e58e 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.it.xlf +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.it.xlf @@ -2,9 +2,39 @@ + + Assembly '{0}' loaded. + Assembly '{0}' loaded. + + + + Assembly '{0}' referenced by '{1}' loaded. + Assembly '{0}' referenced by '{1}' loaded. + + - Could not resolve reference '{0}' in any of the provided search directories. - Non è stato possibile risolvere il riferimento '{0}' in nessuna delle directory di ricerca specificate. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + + + + Loading assemblies '{0}'. + Loading assemblies '{0}'. + + + + Loading assemblies '{0}' ({1}). + Loading assemblies '{0}' ({1}). + + + + Loading assembly '{0}'. + Loading assembly '{0}'. + + + + Loading assembly '{0}' from stream. + Loading assembly '{0}' from stream. @@ -22,6 +52,16 @@ Il flusso specificato per l'assembly '{0}' non contiene metadati da leggere. + + '{0}' + '{0}' + + + + '{0}' ({1}) + '{0}' ({1}) + + Should not be null and contain at least one element. Non deve essere null e deve contenere almeno un elemento. diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.ja.xlf b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.ja.xlf index 22a041a1889b..de55a1d8b387 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.ja.xlf +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.ja.xlf @@ -2,9 +2,39 @@ + + Assembly '{0}' loaded. + Assembly '{0}' loaded. + + + + Assembly '{0}' referenced by '{1}' loaded. + Assembly '{0}' referenced by '{1}' loaded. + + - Could not resolve reference '{0}' in any of the provided search directories. - 指定された検索ディレクトリ内の参照 '{0}' を解決できませんでした。 + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + + + + Loading assemblies '{0}'. + Loading assemblies '{0}'. + + + + Loading assemblies '{0}' ({1}). + Loading assemblies '{0}' ({1}). + + + + Loading assembly '{0}'. + Loading assembly '{0}'. + + + + Loading assembly '{0}' from stream. + Loading assembly '{0}' from stream. @@ -22,6 +52,16 @@ アセンブリ '{0}' に指定されたストリームに読み取るメタデータがありません。送信者。 + + '{0}' + '{0}' + + + + '{0}' ({1}) + '{0}' ({1}) + + Should not be null and contain at least one element. null および 1 つ以上の要素が含まれている必要があります。 diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.ko.xlf b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.ko.xlf index 47b0726a528f..977964897dc6 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.ko.xlf +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.ko.xlf @@ -2,9 +2,39 @@ + + Assembly '{0}' loaded. + Assembly '{0}' loaded. + + + + Assembly '{0}' referenced by '{1}' loaded. + Assembly '{0}' referenced by '{1}' loaded. + + - Could not resolve reference '{0}' in any of the provided search directories. - 제공된 검색 디렉터리에서 참조 '{0}'(을)를 확인할 수 없습니다. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + + + + Loading assemblies '{0}'. + Loading assemblies '{0}'. + + + + Loading assemblies '{0}' ({1}). + Loading assemblies '{0}' ({1}). + + + + Loading assembly '{0}'. + Loading assembly '{0}'. + + + + Loading assembly '{0}' from stream. + Loading assembly '{0}' from stream. @@ -22,6 +52,16 @@ 어셈블리 '{0}'에 대해 제공된 스트림에 읽을 메타데이터가 없습니다. + + '{0}' + '{0}' + + + + '{0}' ({1}) + '{0}' ({1}) + + Should not be null and contain at least one element. Null이 아니어야 하고 요소를 하나 이상 포함해야 합니다. diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.pl.xlf b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.pl.xlf index 2505ca72d789..3cd49ba6d927 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.pl.xlf +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.pl.xlf @@ -2,9 +2,39 @@ + + Assembly '{0}' loaded. + Assembly '{0}' loaded. + + + + Assembly '{0}' referenced by '{1}' loaded. + Assembly '{0}' referenced by '{1}' loaded. + + - Could not resolve reference '{0}' in any of the provided search directories. - Nie można rozpoznać odwołania "{0}" w żadnym z podanych katalogów wyszukiwania. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + + + + Loading assemblies '{0}'. + Loading assemblies '{0}'. + + + + Loading assemblies '{0}' ({1}). + Loading assemblies '{0}' ({1}). + + + + Loading assembly '{0}'. + Loading assembly '{0}'. + + + + Loading assembly '{0}' from stream. + Loading assembly '{0}' from stream. @@ -22,6 +52,16 @@ Podany strumień dla zestawu "{0}" nie ma metadanych, z których można odczytywać. + + '{0}' + '{0}' + + + + '{0}' ({1}) + '{0}' ({1}) + + Should not be null and contain at least one element. Nie może mieć wartości null i powinna zawierać co najmniej jeden element. diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.pt-BR.xlf b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.pt-BR.xlf index 427e22d95228..d127c006417c 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.pt-BR.xlf +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.pt-BR.xlf @@ -2,9 +2,39 @@ + + Assembly '{0}' loaded. + Assembly '{0}' loaded. + + + + Assembly '{0}' referenced by '{1}' loaded. + Assembly '{0}' referenced by '{1}' loaded. + + - Could not resolve reference '{0}' in any of the provided search directories. - Não foi possível resolver a referência '{0}' em nenhum dos diretórios de pesquisa fornecidos. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + + + + Loading assemblies '{0}'. + Loading assemblies '{0}'. + + + + Loading assemblies '{0}' ({1}). + Loading assemblies '{0}' ({1}). + + + + Loading assembly '{0}'. + Loading assembly '{0}'. + + + + Loading assembly '{0}' from stream. + Loading assembly '{0}' from stream. @@ -22,6 +52,16 @@ O fluxo fornecido para o assembly '{0}' não tem metadados para ler. desde. + + '{0}' + '{0}' + + + + '{0}' ({1}) + '{0}' ({1}) + + Should not be null and contain at least one element. Não deve ser nulo e conter pelo menos um elemento. diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.ru.xlf b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.ru.xlf index dc077b51df3a..100bb13e8e96 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.ru.xlf +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.ru.xlf @@ -2,9 +2,39 @@ + + Assembly '{0}' loaded. + Assembly '{0}' loaded. + + + + Assembly '{0}' referenced by '{1}' loaded. + Assembly '{0}' referenced by '{1}' loaded. + + - Could not resolve reference '{0}' in any of the provided search directories. - Не удалось разрешить ссылку "{0}" ни в одном из указанных каталогов поиска. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + + + + Loading assemblies '{0}'. + Loading assemblies '{0}'. + + + + Loading assemblies '{0}' ({1}). + Loading assemblies '{0}' ({1}). + + + + Loading assembly '{0}'. + Loading assembly '{0}'. + + + + Loading assembly '{0}' from stream. + Loading assembly '{0}' from stream. @@ -22,6 +52,16 @@ Указанный поток для сборки "{0}" не имеет метаданных для чтения. От. + + '{0}' + '{0}' + + + + '{0}' ({1}) + '{0}' ({1}) + + Should not be null and contain at least one element. Не должно иметь значение NULL и содержать хотя бы один элемент. diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.tr.xlf b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.tr.xlf index de40e451b609..9964bd5a9b6c 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.tr.xlf +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.tr.xlf @@ -2,9 +2,39 @@ + + Assembly '{0}' loaded. + Assembly '{0}' loaded. + + + + Assembly '{0}' referenced by '{1}' loaded. + Assembly '{0}' referenced by '{1}' loaded. + + - Could not resolve reference '{0}' in any of the provided search directories. - Sağlanan arama dizinlerinin hiçbirinde '{0}' başvurusu çözümlenemedi. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + + + + Loading assemblies '{0}'. + Loading assemblies '{0}'. + + + + Loading assemblies '{0}' ({1}). + Loading assemblies '{0}' ({1}). + + + + Loading assembly '{0}'. + Loading assembly '{0}'. + + + + Loading assembly '{0}' from stream. + Loading assembly '{0}' from stream. @@ -22,6 +52,16 @@ '{0}' bütünleştirilmiş kodu için sağlanan akış, okunacak herhangi bir meta veriye sahip değil. + + '{0}' + '{0}' + + + + '{0}' ({1}) + '{0}' ({1}) + + Should not be null and contain at least one element. Null olmamalı ve en az bir öğe içermelidir. diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.zh-Hans.xlf b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.zh-Hans.xlf index d00e131209cf..b068b1b0fd6a 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.zh-Hans.xlf +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.zh-Hans.xlf @@ -2,9 +2,39 @@ + + Assembly '{0}' loaded. + Assembly '{0}' loaded. + + + + Assembly '{0}' referenced by '{1}' loaded. + Assembly '{0}' referenced by '{1}' loaded. + + - Could not resolve reference '{0}' in any of the provided search directories. - 无法在任何提供的搜索目录中解析引用“{0}”。 + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + + + + Loading assemblies '{0}'. + Loading assemblies '{0}'. + + + + Loading assemblies '{0}' ({1}). + Loading assemblies '{0}' ({1}). + + + + Loading assembly '{0}'. + Loading assembly '{0}'. + + + + Loading assembly '{0}' from stream. + Loading assembly '{0}' from stream. @@ -22,6 +52,16 @@ 为程序集“{0}”提供的流没有任何可供读取的元数据。 + + '{0}' + '{0}' + + + + '{0}' ({1}) + '{0}' ({1}) + + Should not be null and contain at least one element. 不应为 null,并且应至少包含一个元素。 diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.zh-Hant.xlf b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.zh-Hant.xlf index f1dfc166bbe6..397fbb34524a 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.zh-Hant.xlf +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.zh-Hant.xlf @@ -2,9 +2,39 @@ + + Assembly '{0}' loaded. + Assembly '{0}' loaded. + + + + Assembly '{0}' referenced by '{1}' loaded. + Assembly '{0}' referenced by '{1}' loaded. + + - Could not resolve reference '{0}' in any of the provided search directories. - 無法在任何提供的搜尋目錄中解析參考 '{0}'。 + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories. + + + + Loading assemblies '{0}'. + Loading assemblies '{0}'. + + + + Loading assemblies '{0}' ({1}). + Loading assemblies '{0}' ({1}). + + + + Loading assembly '{0}'. + Loading assembly '{0}'. + + + + Loading assembly '{0}' from stream. + Loading assembly '{0}' from stream. @@ -22,6 +52,16 @@ 為元件 '{0}' 提供的資料流程沒有任何可從中讀取的中繼資料。 + + '{0}' + '{0}' + + + + '{0}' ({1}) + '{0}' ({1}) + + Should not be null and contain at least one element. 不應為 Null 且必須包含至少一個元素。 diff --git a/src/Containers/Microsoft.NET.Build.Containers/ContainerBuilder.cs b/src/Containers/Microsoft.NET.Build.Containers/ContainerBuilder.cs index 751c697e6caf..a723bafe4e4b 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/ContainerBuilder.cs +++ b/src/Containers/Microsoft.NET.Build.Containers/ContainerBuilder.cs @@ -6,6 +6,12 @@ namespace Microsoft.NET.Build.Containers; +internal enum KnownImageFormats +{ + OCI, + Docker +} + internal static class ContainerBuilder { internal static async Task ContainerizeAsync( @@ -34,6 +40,7 @@ internal static async Task ContainerizeAsync( string? archiveOutputPath, bool generateLabels, bool generateDigestLabel, + KnownImageFormats? imageFormat, ILoggerFactory loggerFactory, CancellationToken cancellationToken) { @@ -99,6 +106,15 @@ internal static async Task ContainerizeAsync( logger.LogInformation(Strings.ContainerBuilder_StartBuildingImage, imageName, string.Join(",", imageName), sourceImageReference); cancellationToken.ThrowIfCancellationRequested(); + // forcibly change the media type if required + imageBuilder.ManifestMediaType = imageFormat switch + { + null => imageBuilder.ManifestMediaType, + KnownImageFormats.Docker => SchemaTypes.DockerManifestV2, + KnownImageFormats.OCI => SchemaTypes.OciManifestV1, + _ => imageBuilder.ManifestMediaType // should be impossible unless we add to the enum + }; + Layer newLayer = Layer.FromDirectory(publishDirectory.FullName, workingDir, imageBuilder.IsWindows, imageBuilder.ManifestMediaType); imageBuilder.AddLayer(newLayer); imageBuilder.SetWorkingDirectory(workingDir); diff --git a/src/Containers/Microsoft.NET.Build.Containers/ImageBuilder.cs b/src/Containers/Microsoft.NET.Build.Containers/ImageBuilder.cs index 0df6d3fb633a..484fe21bf168 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/ImageBuilder.cs +++ b/src/Containers/Microsoft.NET.Build.Containers/ImageBuilder.cs @@ -19,7 +19,6 @@ internal sealed class ImageBuilder // the mutable internal manifest that we're building by modifying the base and applying customizations private readonly ManifestV2 _manifest; - private readonly string _manifestMediaType; private readonly ImageConfig _baseImageConfig; private readonly ILogger _logger; @@ -32,15 +31,15 @@ internal sealed class ImageBuilder public ImageConfig BaseImageConfig => _baseImageConfig; /// - /// MediaType of the output manifest. + /// MediaType of the output manifest. By default, this will be the same as the base image manifest. /// - public string ManifestMediaType => _manifestMediaType; // output the same media type as the base image manifest. + public string ManifestMediaType { get; set; } internal ImageBuilder(ManifestV2 manifest, string manifestMediaType, ImageConfig baseImageConfig, ILogger logger) { _baseImageManifest = manifest; _manifest = new ManifestV2() { SchemaVersion = manifest.SchemaVersion, Config = manifest.Config, Layers = new(manifest.Layers), MediaType = manifest.MediaType }; - _manifestMediaType = manifestMediaType; + ManifestMediaType = manifestMediaType; _baseImageConfig = baseImageConfig; _logger = logger; } @@ -70,14 +69,20 @@ internal BuiltImage Build() ManifestConfig newManifestConfig = _manifest.Config with { digest = imageDigest, - size = imageSize + size = imageSize, + mediaType = ManifestMediaType switch + { + SchemaTypes.OciManifestV1 => SchemaTypes.OciImageConfigV1, + SchemaTypes.DockerManifestV2 => SchemaTypes.DockerContainerV1, + _ => SchemaTypes.OciImageConfigV1 // opinion - defaulting to modern here, but really this should never happen + } }; ManifestV2 newManifest = new ManifestV2() { Config = newManifestConfig, SchemaVersion = _manifest.SchemaVersion, - MediaType = _manifest.MediaType, + MediaType = ManifestMediaType, Layers = _manifest.Layers }; diff --git a/src/Containers/Microsoft.NET.Build.Containers/KnownStrings.cs b/src/Containers/Microsoft.NET.Build.Containers/KnownStrings.cs index 7a6ddc08c7c4..e8cfae873a1c 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/KnownStrings.cs +++ b/src/Containers/Microsoft.NET.Build.Containers/KnownStrings.cs @@ -41,6 +41,7 @@ public static class Properties public static readonly string PublishTrimmed = nameof(PublishTrimmed); public static readonly string PublishSelfContained = nameof(PublishSelfContained); public static readonly string InvariantGlobalization = nameof(InvariantGlobalization); + public static readonly string InvariantTimezone = nameof(InvariantTimezone); } public static class Items diff --git a/src/Containers/Microsoft.NET.Build.Containers/PublicAPI/net10.0/PublicAPI.Unshipped.txt b/src/Containers/Microsoft.NET.Build.Containers/PublicAPI/net10.0/PublicAPI.Unshipped.txt index f11ef4cc85f9..7b39f7d841ee 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/PublicAPI/net10.0/PublicAPI.Unshipped.txt +++ b/src/Containers/Microsoft.NET.Build.Containers/PublicAPI/net10.0/PublicAPI.Unshipped.txt @@ -243,6 +243,8 @@ Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GenerateDigestLabel.get -> b Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GenerateDigestLabel.set -> void Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerNames.get -> Microsoft.Build.Framework.ITaskItem![]! Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerNames.set -> void +Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ImageFormat.get -> string? +Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ImageFormat.set -> void Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerEnvironmentVariables.get -> Microsoft.Build.Framework.ITaskItem![]! Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerEnvironmentVariables.set -> void diff --git a/src/Containers/Microsoft.NET.Build.Containers/PublicAPI/net472/PublicAPI.Unshipped.txt b/src/Containers/Microsoft.NET.Build.Containers/PublicAPI/net472/PublicAPI.Unshipped.txt index 5289498137e7..f1e042a7e104 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/Containers/Microsoft.NET.Build.Containers/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -90,6 +90,8 @@ Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GenerateDigestLabel.get -> b Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GenerateDigestLabel.set -> void Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerNames.get -> Microsoft.Build.Framework.ITaskItem![]! Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerNames.set -> void +Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ImageFormat.get -> string? +Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ImageFormat.set -> void override Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ToolName.get -> string! override Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GenerateCommandLineCommands() -> string! override Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GenerateFullPathToTool() -> string! diff --git a/src/Containers/Microsoft.NET.Build.Containers/Registry/SchemaTypes.cs b/src/Containers/Microsoft.NET.Build.Containers/Registry/SchemaTypes.cs index 8021f652f72d..f7ae91a19e8b 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Registry/SchemaTypes.cs +++ b/src/Containers/Microsoft.NET.Build.Containers/Registry/SchemaTypes.cs @@ -9,8 +9,11 @@ internal class SchemaTypes internal const string DockerContainerV1 = "application/vnd.docker.container.image.v1+json"; internal const string DockerManifestListV2 = "application/vnd.docker.distribution.manifest.list.v2+json"; internal const string DockerManifestV2 = "application/vnd.docker.distribution.manifest.v2+json"; + internal const string OciManifestV1 = "application/vnd.oci.image.manifest.v1+json"; // https://containers.gitbook.io/build-containers-the-hard-way/#registry-format-oci-image-manifest internal const string OciImageIndexV1 = "application/vnd.oci.image.index.v1+json"; + internal const string OciImageConfigV1 = "application/vnd.oci.image.config.v1+json"; + internal const string DockerLayerGzip = "application/vnd.docker.image.rootfs.diff.tar.gzip"; internal const string OciLayerGzipV1 = "application/vnd.oci.image.layer.v1.tar+gzip"; } diff --git a/src/Containers/Microsoft.NET.Build.Containers/Resources/Strings.Designer.cs b/src/Containers/Microsoft.NET.Build.Containers/Resources/Strings.Designer.cs index aff92942f408..9cf5fb285768 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Resources/Strings.Designer.cs +++ b/src/Containers/Microsoft.NET.Build.Containers/Resources/Strings.Designer.cs @@ -10,8 +10,8 @@ namespace Microsoft.NET.Build.Containers.Resources { using System; - - + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -23,15 +23,15 @@ namespace Microsoft.NET.Build.Containers.Resources { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Strings { - + private static global::System.Resources.ResourceManager resourceMan; - + private static global::System.Globalization.CultureInfo resourceCulture; - + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Strings() { } - + /// /// Returns the cached ResourceManager instance used by this class. /// @@ -45,7 +45,7 @@ internal Strings() { return resourceMan; } } - + /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. @@ -59,7 +59,7 @@ internal Strings() { resourceCulture = value; } } - + /// /// Looks up a localized string similar to CONTAINER0000: Value for unit test {0}. /// @@ -68,7 +68,7 @@ internal static string _Test { return ResourceManager.GetString("_Test", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER1002: Request to Amazon Elastic Container Registry failed prematurely. This is often caused when the target repository does not exist in the registry.. /// @@ -77,7 +77,7 @@ internal static string AmazonRegistryFailed { return ResourceManager.GetString("AmazonRegistryFailed", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2008: Both {0} and {1} were provided, but only one or the other is allowed.. /// @@ -86,7 +86,7 @@ internal static string AmbiguousTags { return ResourceManager.GetString("AmbiguousTags", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2025: ContainerAppCommandArgs are provided without specifying a ContainerAppCommand.. /// @@ -95,7 +95,7 @@ internal static string AppCommandArgsSetNoAppCommand { return ResourceManager.GetString("AppCommandArgsSetNoAppCommand", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2026: ContainerAppCommand and ContainerAppCommandArgs must be empty when ContainerAppCommandInstruction is '{0}'.. /// @@ -104,7 +104,7 @@ internal static string AppCommandSetNotUsed { return ResourceManager.GetString("AppCommandSetNotUsed", resourceCulture); } } - + /// /// Looks up a localized string similar to local archive at '{0}'. /// @@ -113,7 +113,7 @@ internal static string ArchiveRegistry_PushInfo { return ResourceManager.GetString("ArchiveRegistry_PushInfo", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2022: The base image has an entrypoint that will be overwritten to start the application. Set ContainerAppCommandInstruction to 'Entrypoint' if this is desired. To preserve the base image entrypoint, set ContainerAppCommandInstruction to 'DefaultArgs'.. /// @@ -122,7 +122,7 @@ internal static string BaseEntrypointOverwritten { return ResourceManager.GetString("BaseEntrypointOverwritten", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2009: Could not parse {0}: {1}. /// @@ -131,7 +131,7 @@ internal static string BaseImageNameParsingFailed { return ResourceManager.GetString("BaseImageNameParsingFailed", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2020: {0} does not specify a registry and will be pulled from Docker Hub. Please prefix the name with the image registry, for example: '{1}/<image>'.. /// @@ -140,7 +140,7 @@ internal static string BaseImageNameRegistryFallback { return ResourceManager.GetString("BaseImageNameRegistryFallback", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2013: {0} had spaces in it, replacing with dashes.. /// @@ -149,7 +149,7 @@ internal static string BaseImageNameWithSpaces { return ResourceManager.GetString("BaseImageNameWithSpaces", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER1011: Couldn't find matching base image for {0} that matches RuntimeIdentifier {1}.. /// @@ -158,7 +158,7 @@ internal static string BaseImageNotFound { return ResourceManager.GetString("BaseImageNotFound", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER1001: Failed to upload blob using {0}; received status code '{1}'.. /// @@ -167,7 +167,7 @@ internal static string BlobUploadFailed { return ResourceManager.GetString("BlobUploadFailed", resourceCulture); } } - + /// /// Looks up a localized string similar to Building image index '{0}' on top of manifests {1}.. /// @@ -176,7 +176,7 @@ internal static string BuildingImageIndex { return ResourceManager.GetString("BuildingImageIndex", resourceCulture); } } - + /// /// Looks up a localized string similar to Pushed image '{0}' to {1}.. /// @@ -185,7 +185,7 @@ internal static string ContainerBuilder_ImageUploadedToLocalDaemon { return ResourceManager.GetString("ContainerBuilder_ImageUploadedToLocalDaemon", resourceCulture); } } - + /// /// Looks up a localized string similar to Pushed image '{0}' to registry '{1}'.. /// @@ -194,7 +194,7 @@ internal static string ContainerBuilder_ImageUploadedToRegistry { return ResourceManager.GetString("ContainerBuilder_ImageUploadedToRegistry", resourceCulture); } } - + /// /// Looks up a localized string similar to Building image '{0}' with tags '{1}' on top of base image '{2}'.. /// @@ -203,7 +203,7 @@ internal static string ContainerBuilder_StartBuildingImage { return ResourceManager.GetString("ContainerBuilder_StartBuildingImage", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER3001: Failed creating {0} process.. /// @@ -212,7 +212,7 @@ internal static string ContainerRuntimeProcessCreationFailed { return ResourceManager.GetString("ContainerRuntimeProcessCreationFailed", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER1007: Could not deserialize token from JSON.. /// @@ -221,7 +221,7 @@ internal static string CouldntDeserializeJsonToken { return ResourceManager.GetString("CouldntDeserializeJsonToken", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2012: Could not recognize registry '{0}'.. /// @@ -230,7 +230,7 @@ internal static string CouldntRecognizeRegistry { return ResourceManager.GetString("CouldntRecognizeRegistry", resourceCulture); } } - + /// /// Looks up a localized string similar to local registry via '{0}'. /// @@ -239,7 +239,7 @@ internal static string DockerCli_PushInfo { return ResourceManager.GetString("DockerCli_PushInfo", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER3002: Failed to get docker info({0})\n{1}\n{2}. /// @@ -248,7 +248,7 @@ internal static string DockerInfoFailed { return ResourceManager.GetString("DockerInfoFailed", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER3002: Failed to get docker info: {0}. /// @@ -257,7 +257,7 @@ internal static string DockerInfoFailed_Ex { return ResourceManager.GetString("DockerInfoFailed_Ex", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER4006: Property '{0}' is empty or contains whitespace and will be ignored.. /// @@ -266,7 +266,7 @@ internal static string EmptyOrWhitespacePropertyIgnored { return ResourceManager.GetString("EmptyOrWhitespacePropertyIgnored", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER4004: Items '{0}' contain empty item(s) which will be ignored.. /// @@ -275,7 +275,7 @@ internal static string EmptyValuesIgnored { return ResourceManager.GetString("EmptyValuesIgnored", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2023: A ContainerEntrypoint and ContainerAppCommandArgs are provided. ContainerAppInstruction must be set to configure how the application is started. Valid instructions are {0}.. /// @@ -284,7 +284,7 @@ internal static string EntrypointAndAppCommandArgsSetNoAppCommandInstruction { return ResourceManager.GetString("EntrypointAndAppCommandArgsSetNoAppCommandInstruction", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2024: ContainerEntrypointArgs are provided without specifying a ContainerEntrypoint.. /// @@ -293,7 +293,7 @@ internal static string EntrypointArgsSetNoEntrypoint { return ResourceManager.GetString("EntrypointArgsSetNoEntrypoint", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2029: ContainerEntrypointArgsSet are provided. Change to use ContainerAppCommandArgs for arguments that must always be set, or ContainerDefaultArgs for arguments that can be overridden when the container is created.. /// @@ -302,7 +302,7 @@ internal static string EntrypointArgsSetPreferAppCommandArgs { return ResourceManager.GetString("EntrypointArgsSetPreferAppCommandArgs", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2028: ContainerEntrypoint can not be combined with ContainerAppCommandInstruction '{0}'.. /// @@ -311,7 +311,7 @@ internal static string EntrypointConflictAppCommand { return ResourceManager.GetString("EntrypointConflictAppCommand", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2027: A ContainerEntrypoint is provided. ContainerAppInstruction must be set to configure how the application is started. Valid instructions are {0}.. /// @@ -320,7 +320,7 @@ internal static string EntrypointSetNoAppCommandInstruction { return ResourceManager.GetString("EntrypointSetNoAppCommandInstruction", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER1008: Failed retrieving credentials for "{0}": {1}. /// @@ -329,7 +329,7 @@ internal static string FailedRetrievingCredentials { return ResourceManager.GetString("FailedRetrievingCredentials", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2030: GenerateLabels was disabled but GenerateDigestLabel was enabled - no digest label will be created.. /// @@ -338,7 +338,7 @@ internal static string GenerateDigestLabelWithoutGenerateLabels { return ResourceManager.GetString("GenerateDigestLabelWithoutGenerateLabels", resourceCulture); } } - + /// /// Looks up a localized string similar to No host object detected.. /// @@ -347,7 +347,7 @@ internal static string HostObjectNotDetected { return ResourceManager.GetString("HostObjectNotDetected", resourceCulture); } } - + /// /// Looks up a localized string similar to Pushed image index '{0}' to registry '{1}'.. /// @@ -356,7 +356,7 @@ internal static string ImageIndexUploadedToRegistry { return ResourceManager.GetString("ImageIndexUploadedToRegistry", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER1009: Failed to load image from local registry. stdout: {0}. /// @@ -365,7 +365,7 @@ internal static string ImageLoadFailed { return ResourceManager.GetString("ImageLoadFailed", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER1010: Pulling images from local registry is not supported.. /// @@ -374,7 +374,7 @@ internal static string ImagePullNotSupported { return ResourceManager.GetString("ImagePullNotSupported", resourceCulture); } } - + /// /// Looks up a localized string similar to Cannot create manifest list (image index) because no images were provided.. /// @@ -383,7 +383,16 @@ internal static string ImagesEmpty { return ResourceManager.GetString("ImagesEmpty", resourceCulture); } } - + + /// + /// Looks up a localized string similar to CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'.. + /// + internal static string InvalidContainerImageFormat { + get { + return ResourceManager.GetString("InvalidContainerImageFormat", resourceCulture); + } + } + /// /// Looks up a localized string similar to CONTAINER2015: {0}: '{1}' was not a valid Environment Variable. Ignoring.. /// @@ -392,7 +401,7 @@ internal static string InvalidEnvVar { return ResourceManager.GetString("InvalidEnvVar", resourceCulture); } } - + /// /// Looks up a localized string similar to Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata.. /// @@ -401,7 +410,7 @@ internal static string InvalidImageMetadata { return ResourceManager.GetString("InvalidImageMetadata", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2005: The inferred image name '{0}' contains entirely invalid characters. The valid characters for an image name are alphanumeric characters, -, /, or _, and the image name must start with an alphanumeric character.. /// @@ -410,7 +419,7 @@ internal static string InvalidImageName_EntireNameIsInvalidCharacters { return ResourceManager.GetString("InvalidImageName_EntireNameIsInvalidCharacters", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2005: The first character of the image name '{0}' must be a lowercase letter or a digit and all characters in the name must be an alphanumeric character, -, /, or _.. /// @@ -419,7 +428,7 @@ internal static string InvalidImageName_NonAlphanumericStartCharacter { return ResourceManager.GetString("InvalidImageName_NonAlphanumericStartCharacter", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2017: A ContainerPort item was provided with an invalid port number '{0}'. ContainerPort items must have an Include value that is an integer, and a Type value that is either 'tcp' or 'udp'.. /// @@ -428,7 +437,7 @@ internal static string InvalidPort_Number { return ResourceManager.GetString("InvalidPort_Number", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2017: A ContainerPort item was provided with an invalid port number '{0}' and an invalid port type '{1}'. ContainerPort items must have an Include value that is an integer, and a Type value that is either 'tcp' or 'udp'.. /// @@ -437,7 +446,7 @@ internal static string InvalidPort_NumberAndType { return ResourceManager.GetString("InvalidPort_NumberAndType", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2017: A ContainerPort item was provided with an invalid port type '{0}'. ContainerPort items must have an Include value that is an integer, and a Type value that is either 'tcp' or 'udp'.. /// @@ -446,7 +455,7 @@ internal static string InvalidPort_Type { return ResourceManager.GetString("InvalidPort_Type", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2018: Invalid SDK prerelease version '{0}' - only 'rc' and 'preview' are supported.. /// @@ -455,7 +464,7 @@ internal static string InvalidSdkPrereleaseVersion { return ResourceManager.GetString("InvalidSdkPrereleaseVersion", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2019: Invalid SDK semantic version '{0}'.. /// @@ -464,7 +473,7 @@ internal static string InvalidSdkVersion { return ResourceManager.GetString("InvalidSdkVersion", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2007: Invalid {0} provided: {1}. Image tags must be alphanumeric, underscore, hyphen, or period.. /// @@ -473,7 +482,7 @@ internal static string InvalidTag { return ResourceManager.GetString("InvalidTag", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2010: Invalid {0} provided: {1}. {0} must be a semicolon-delimited list of valid image tags. Image tags must be alphanumeric, underscore, hyphen, or period.. /// @@ -482,7 +491,7 @@ internal static string InvalidTags { return ResourceManager.GetString("InvalidTags", resourceCulture); } } - + /// /// Looks up a localized string similar to Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none.. /// @@ -491,7 +500,7 @@ internal static string InvalidTargetRuntimeIdentifiers { return ResourceManager.GetString("InvalidTargetRuntimeIdentifiers", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER1003: Token response had neither token nor access_token.. /// @@ -500,7 +509,7 @@ internal static string InvalidTokenResponse { return ResourceManager.GetString("InvalidTokenResponse", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER4005: Item '{0}' contains items without metadata 'Value', and they will be ignored.. /// @@ -509,7 +518,7 @@ internal static string ItemsWithoutMetadata { return ResourceManager.GetString("ItemsWithoutMetadata", resourceCulture); } } - + /// /// Looks up a localized string similar to Error while reading daemon config: {0}. /// @@ -518,7 +527,7 @@ internal static string LocalDocker_FailedToGetConfig { return ResourceManager.GetString("LocalDocker_FailedToGetConfig", resourceCulture); } } - + /// /// Looks up a localized string similar to The daemon server reported errors: {0}. /// @@ -527,7 +536,7 @@ internal static string LocalDocker_LocalDaemonErrors { return ResourceManager.GetString("LocalDocker_LocalDaemonErrors", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER1012: The local registry is not available, but pushing to a local registry was requested.. /// @@ -536,7 +545,7 @@ internal static string LocalRegistryNotAvailable { return ResourceManager.GetString("LocalRegistryNotAvailable", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2004: Unable to download layer with descriptor '{0}' from registry '{1}' because it does not exist.. /// @@ -545,7 +554,7 @@ internal static string MissingLinkToRegistry { return ResourceManager.GetString("MissingLinkToRegistry", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2016: ContainerPort item '{0}' does not specify the port number. Please ensure the item's Include is a port number, for example '<ContainerPort Include="80" />'. /// @@ -554,7 +563,7 @@ internal static string MissingPortNumber { return ResourceManager.GetString("MissingPortNumber", resourceCulture); } } - + /// /// Looks up a localized string similar to 'mediaType' of manifests should be the same in manifest list (image index).. /// @@ -563,7 +572,7 @@ internal static string MixedMediaTypes { return ResourceManager.GetString("MixedMediaTypes", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER1004: No RequestUri specified.. /// @@ -572,7 +581,7 @@ internal static string NoRequestUriSpecified { return ResourceManager.GetString("NoRequestUriSpecified", resourceCulture); } } - + /// /// Looks up a localized string similar to '{0}' was not a valid container image name, it was normalized to '{1}'. /// @@ -581,7 +590,7 @@ internal static string NormalizedContainerName { return ResourceManager.GetString("NormalizedContainerName", resourceCulture); } } - + /// /// Looks up a localized string similar to Unable to create tarball for oci image with multiple tags.. /// @@ -590,7 +599,7 @@ internal static string OciImageMultipleTagsNotSupported { return ResourceManager.GetString("OciImageMultipleTagsNotSupported", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2011: {0} '{1}' does not exist. /// @@ -599,7 +608,7 @@ internal static string PublishDirectoryDoesntExist { return ResourceManager.GetString("PublishDirectoryDoesntExist", resourceCulture); } } - + /// /// Looks up a localized string similar to Uploaded config to registry.. /// @@ -608,7 +617,7 @@ internal static string Registry_ConfigUploaded { return ResourceManager.GetString("Registry_ConfigUploaded", resourceCulture); } } - + /// /// Looks up a localized string similar to Uploading config to registry at blob '{0}',. /// @@ -617,7 +626,7 @@ internal static string Registry_ConfigUploadStarted { return ResourceManager.GetString("Registry_ConfigUploadStarted", resourceCulture); } } - + /// /// Looks up a localized string similar to Layer '{0}' already exists.. /// @@ -626,7 +635,7 @@ internal static string Registry_LayerExists { return ResourceManager.GetString("Registry_LayerExists", resourceCulture); } } - + /// /// Looks up a localized string similar to Finished uploading layer '{0}' to '{1}'.. /// @@ -635,7 +644,7 @@ internal static string Registry_LayerUploaded { return ResourceManager.GetString("Registry_LayerUploaded", resourceCulture); } } - + /// /// Looks up a localized string similar to Uploading layer '{0}' to '{1}'.. /// @@ -644,7 +653,7 @@ internal static string Registry_LayerUploadStarted { return ResourceManager.GetString("Registry_LayerUploadStarted", resourceCulture); } } - + /// /// Looks up a localized string similar to Uploaded manifest to '{0}'.. /// @@ -653,7 +662,7 @@ internal static string Registry_ManifestUploaded { return ResourceManager.GetString("Registry_ManifestUploaded", resourceCulture); } } - + /// /// Looks up a localized string similar to Uploading manifest to registry '{0}' as blob '{1}'.. /// @@ -662,7 +671,7 @@ internal static string Registry_ManifestUploadStarted { return ResourceManager.GetString("Registry_ManifestUploadStarted", resourceCulture); } } - + /// /// Looks up a localized string similar to Uploaded tag '{0}' to '{1}'.. /// @@ -671,7 +680,7 @@ internal static string Registry_TagUploaded { return ResourceManager.GetString("Registry_TagUploaded", resourceCulture); } } - + /// /// Looks up a localized string similar to Uploading tag '{0}' to '{1}'.. /// @@ -680,7 +689,7 @@ internal static string Registry_TagUploadStarted { return ResourceManager.GetString("Registry_TagUploadStarted", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER1017: Unable to communicate with the registry '{0}'.. /// @@ -689,7 +698,7 @@ internal static string RegistryOperationFailed { return ResourceManager.GetString("RegistryOperationFailed", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER1013: Failed to push to the output registry: {0}. /// @@ -698,7 +707,7 @@ internal static string RegistryOutputPushFailed { return ResourceManager.GetString("RegistryOutputPushFailed", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER1014: Manifest pull failed.. /// @@ -707,7 +716,7 @@ internal static string RegistryPullFailed { return ResourceManager.GetString("RegistryPullFailed", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER1005: Registry push failed; received status code '{0}'.. /// @@ -716,7 +725,7 @@ internal static string RegistryPushFailed { return ResourceManager.GetString("RegistryPushFailed", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER1015: Unable to access the repository '{0}' at tag '{1}' in the registry '{2}'. Please confirm that this name and tag are present in the registry.. /// @@ -725,7 +734,7 @@ internal static string RepositoryNotFound { return ResourceManager.GetString("RepositoryNotFound", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER4003: Required '{0}' items contain empty items.. /// @@ -734,7 +743,7 @@ internal static string RequiredItemsContainsEmptyItems { return ResourceManager.GetString("RequiredItemsContainsEmptyItems", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER4002: Required '{0}' items were not set.. /// @@ -743,7 +752,7 @@ internal static string RequiredItemsNotSet { return ResourceManager.GetString("RequiredItemsNotSet", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER4001: Required property '{0}' was not set or empty.. /// @@ -752,7 +761,7 @@ internal static string RequiredPropertyNotSetOrEmpty { return ResourceManager.GetString("RequiredPropertyNotSetOrEmpty", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER1006: Too many retries, stopping.. /// @@ -761,7 +770,7 @@ internal static string TooManyRetries { return ResourceManager.GetString("TooManyRetries", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER1016: Unable to access the repository '{0}' in the registry '{1}'. Please confirm your credentials are correct and that you have access to this repository and registry.. /// @@ -770,7 +779,7 @@ internal static string UnableToAccessRepository { return ResourceManager.GetString("UnableToAccessRepository", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2021: Unknown AppCommandInstruction '{0}'. Valid instructions are {1}.. /// @@ -779,7 +788,7 @@ internal static string UnknownAppCommandInstruction { return ResourceManager.GetString("UnknownAppCommandInstruction", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2002: Unknown local registry type '{0}'. Valid local container registry types are {1}.. /// @@ -788,7 +797,7 @@ internal static string UnknownLocalRegistryType { return ResourceManager.GetString("UnknownLocalRegistryType", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2003: The manifest for {0}:{1} from registry {2} was an unknown type: {3}. Please raise an issue at https://github.com/dotnet/sdk-container-builds/issues with this message.. /// @@ -797,7 +806,7 @@ internal static string UnknownMediaType { return ResourceManager.GetString("UnknownMediaType", resourceCulture); } } - + /// /// Looks up a localized string similar to CONTAINER2001: Unrecognized mediaType '{0}'.. /// @@ -806,7 +815,7 @@ internal static string UnrecognizedMediaType { return ResourceManager.GetString("UnrecognizedMediaType", resourceCulture); } } - + /// /// Looks up a localized string similar to Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'.. /// @@ -815,7 +824,7 @@ internal static string UnsupportedMediaType { return ResourceManager.GetString("UnsupportedMediaType", resourceCulture); } } - + /// /// Looks up a localized string similar to Unable to create tarball for mediaType '{0}'.. /// diff --git a/src/Containers/Microsoft.NET.Build.Containers/Resources/Strings.resx b/src/Containers/Microsoft.NET.Build.Containers/Resources/Strings.resx index 57168a5f08bf..fd26dda65b56 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Resources/Strings.resx +++ b/src/Containers/Microsoft.NET.Build.Containers/Resources/Strings.resx @@ -456,4 +456,8 @@ CONTAINER2030: GenerateLabels was disabled but GenerateDigestLabel was enabled - no digest label will be created. {StrBegins="CONTAINER2030: "} + + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + {StrBegins="CONTAINER2031: "} + diff --git a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.cs.xlf b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.cs.xlf index f9b14762b904..b44981ef4270 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.cs.xlf +++ b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.cs.xlf @@ -59,7 +59,7 @@ Building image index '{0}' on top of manifests {1}. - Building image index '{0}' on top of manifests {1}. + Vytváření '{0}' indexu obrázků nad manifesty {1}. {0} is the name of the image index and its tag, {1} is the list of manifests digests @@ -161,7 +161,7 @@ Pushed image index '{0}' to registry '{1}'. - Pushed image index '{0}' to registry '{1}'. + Image s indexem {0} byla vložena do registru {1}. @@ -176,9 +176,14 @@ Cannot create manifest list (image index) because no images were provided. - Cannot create manifest list (image index) because no images were provided. + Seznam manifestů (index image) nelze vytvořit, protože nebyly zadány žádné obrázky. + + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + {StrBegins="CONTAINER2031: "} + CONTAINER2015: {0}: '{1}' was not a valid Environment Variable. Ignoring. CONTAINER2015: {0}: '{1}' není platná proměnná prostředí. Ignorování. @@ -186,7 +191,7 @@ Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. - Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. + Seznam manifestů (index image) nelze vytvořit, protože zadané obrázky jsou neplatné. Položky musí mít metadata Config, Manifest, ManifestMediaType a ManifestDigest. @@ -236,7 +241,7 @@ Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. - Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. + Neplatný řetězec[] TargetRuntimeIdentifiers Buď by všechny měly být linux-musl, nebo žádné. @@ -276,7 +281,7 @@ 'mediaType' of manifests should be the same in manifest list (image index). - 'mediaType' of manifests should be the same in manifest list (image index). + MediaType manifestů by měl být stejný v seznamu manifestů (index image). @@ -416,7 +421,7 @@ Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. - Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. + Nejde vytvořit seznam manifestů (index image) pro poskytnutý mediaType = '{0}'. diff --git a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.de.xlf b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.de.xlf index 9aac91628a8a..ddb19050d638 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.de.xlf +++ b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.de.xlf @@ -59,7 +59,7 @@ Building image index '{0}' on top of manifests {1}. - Building image index '{0}' on top of manifests {1}. + Imageindex wird '{0}' über manifesten {1} erstellt. {0} is the name of the image index and its tag, {1} is the list of manifests digests @@ -161,7 +161,7 @@ Pushed image index '{0}' to registry '{1}'. - Pushed image index '{0}' to registry '{1}'. + Bildindex „{0}“ wurde in die Registrierung „{1}“ gepusht. @@ -176,9 +176,14 @@ Cannot create manifest list (image index) because no images were provided. - Cannot create manifest list (image index) because no images were provided. + Die Manifestliste (Imageindex) kann nicht erstellt werden, da keine Bilder bereitgestellt wurden. + + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + {StrBegins="CONTAINER2031: "} + CONTAINER2015: {0}: '{1}' was not a valid Environment Variable. Ignoring. CONTAINER2015: {0}: „{1}“ war keine gültige Umgebungsvariable. Sie wird ignoriert. @@ -186,7 +191,7 @@ Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. - Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. + Die Manifestliste (Imageindex) kann nicht erstellt werden, da die angegebenen Bilder ungültig sind. Elemente müssen die Metadaten "Config", "Manifest", "ManifestMediaType" und "ManifestDigest" aufweisen. @@ -236,7 +241,7 @@ Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. - Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. + Ungültige string[] TargetRuntimeIdentifiers. Entweder sollten alle "linux-musl" oder "none" sein. @@ -276,7 +281,7 @@ 'mediaType' of manifests should be the same in manifest list (image index). - 'mediaType' of manifests should be the same in manifest list (image index). + "mediaType" der Manifeste sollte in der Manifestliste (Bildindex) identisch sein. @@ -416,7 +421,7 @@ Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. - Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. + Die Manifestliste (Imageindex) für den angegebenen "mediaType" = '{0}' kann nicht erstellt werden. diff --git a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.es.xlf b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.es.xlf index f943f93fa92c..dece60a72610 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.es.xlf +++ b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.es.xlf @@ -59,7 +59,7 @@ Building image index '{0}' on top of manifests {1}. - Building image index '{0}' on top of manifests {1}. + Generando '{0}' de índice de imagen encima de los manifiestos {1}. {0} is the name of the image index and its tag, {1} is the list of manifests digests @@ -161,7 +161,7 @@ Pushed image index '{0}' to registry '{1}'. - Pushed image index '{0}' to registry '{1}'. + Imagen “{0}” insertada en el registro “{1}”. @@ -176,9 +176,14 @@ Cannot create manifest list (image index) because no images were provided. - Cannot create manifest list (image index) because no images were provided. + No se puede crear la lista de manifiestos (índice de imágenes) porque no se proporcionaron imágenes. + + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + {StrBegins="CONTAINER2031: "} + CONTAINER2015: {0}: '{1}' was not a valid Environment Variable. Ignoring. CONTAINER2015: {0}: "{1}" no era una variable de entorno válida. Ignorando. @@ -186,7 +191,7 @@ Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. - Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. + No se puede crear la lista de manifiestos (índice de imagen) porque las imágenes proporcionadas no son válidas. Los elementos deben tener metadatos 'Config', 'Manifest', 'ManifestMediaType' y 'ManifestDigest'. @@ -236,7 +241,7 @@ Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. - Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. + String[] TargetRuntimeIdentifiers no válido. Todos deben ser 'linux-musl' o ninguno. @@ -276,7 +281,7 @@ 'mediaType' of manifests should be the same in manifest list (image index). - 'mediaType' of manifests should be the same in manifest list (image index). + El valor de "mediaType" de los manifiestos debe ser el mismo en la lista de manifiestos (índice de imagen). @@ -416,7 +421,7 @@ Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. - Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. + No se puede crear la lista de manifiestos (índice de imagen) para el 'mediaType' = '{0}' proporcionado. diff --git a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.fr.xlf b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.fr.xlf index 436a7f45faba..251a6f066724 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.fr.xlf +++ b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.fr.xlf @@ -59,7 +59,7 @@ Building image index '{0}' on top of manifests {1}. - Building image index '{0}' on top of manifests {1}. + Génération de l’index d’image '{0}' au-dessus des manifestes {1}. {0} is the name of the image index and its tag, {1} is the list of manifests digests @@ -161,7 +161,7 @@ Pushed image index '{0}' to registry '{1}'. - Pushed image index '{0}' to registry '{1}'. + L’index de l’image « {0} » a été envoyé vers le registre « {1} ». @@ -176,9 +176,14 @@ Cannot create manifest list (image index) because no images were provided. - Cannot create manifest list (image index) because no images were provided. + Impossible de créer la liste de manifeste (index d’images) car aucune image n’a été fournie. + + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + {StrBegins="CONTAINER2031: "} + CONTAINER2015: {0}: '{1}' was not a valid Environment Variable. Ignoring. CONTAINER2015: {0} : '{1}' n’était pas une variable d’environnement valide. Ignorant. @@ -186,7 +191,7 @@ Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. - Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. + Impossible de créer la liste de manifeste (index d’images) car les images fournies ne sont pas valides. Les éléments doivent avoir les métadonnées 'Config', 'Manifest', 'ManifestMediaType' et 'ManifestDigest'. @@ -236,7 +241,7 @@ Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. - Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. + Chaîne[] TargetRuntimeIdentifiers non valide. Soit tout doit être 'linux-keyl', soit aucun. @@ -276,7 +281,7 @@ 'mediaType' of manifests should be the same in manifest list (image index). - 'mediaType' of manifests should be the same in manifest list (image index). + 'mediaType' des manifestes doit être identique dans la liste des manifestes (index d’images). @@ -416,7 +421,7 @@ Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. - Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. + Impossible de créer une liste de manifeste (index d’image) pour le 'mediaType' = '{0}' fourni. diff --git a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.it.xlf b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.it.xlf index 9209a128d3a9..6650435cb2e9 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.it.xlf +++ b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.it.xlf @@ -59,7 +59,7 @@ Building image index '{0}' on top of manifests {1}. - Building image index '{0}' on top of manifests {1}. + Compilazione dell'indice delle immagini '{0}' sui manifesti {1}. {0} is the name of the image index and its tag, {1} is the list of manifests digests @@ -161,7 +161,7 @@ Pushed image index '{0}' to registry '{1}'. - Pushed image index '{0}' to registry '{1}'. + È stato eseguito il push dell'indice immagine "{0}" nel registro "{1}". @@ -176,9 +176,14 @@ Cannot create manifest list (image index) because no images were provided. - Cannot create manifest list (image index) because no images were provided. + Non è possibile creare l'elenco manifesto (indice delle immagini) perché non sono state specificate immagini. + + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + {StrBegins="CONTAINER2031: "} + CONTAINER2015: {0}: '{1}' was not a valid Environment Variable. Ignoring. CONTAINER2015: {0}: '{1}' non è una variabile di ambiente valida. Il valore verrà ignorato. @@ -186,7 +191,7 @@ Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. - Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. + Non è possibile creare l'elenco manifesto (indice delle immagini) perché le immagini specificate non sono valide. Gli elementi devono contenere i metadati 'Config', 'Manifest', 'ManifestMediaType' e 'ManifestDigest'. @@ -236,7 +241,7 @@ Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. - Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. + Stringa non valida[] TargetRuntimeIdentifiers. Tutti devono essere 'linux-musl' o nessuno. @@ -276,7 +281,7 @@ 'mediaType' of manifests should be the same in manifest list (image index). - 'mediaType' of manifests should be the same in manifest list (image index). + 'mediaType' dei manifesti deve essere lo stesso nell'elenco di manifesti (indice immagine). @@ -416,7 +421,7 @@ Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. - Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. + Non è possibile creare l'elenco manifesto (indice immagine) per l'elemento 'mediaType' specificato = '{0}'. diff --git a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.ja.xlf b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.ja.xlf index 3646bde68d76..9ec7f8022fe0 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.ja.xlf +++ b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.ja.xlf @@ -59,7 +59,7 @@ Building image index '{0}' on top of manifests {1}. - Building image index '{0}' on top of manifests {1}. + マニフェスト {1} の上にイメージ インデックス '{0}' を構築しています。 {0} is the name of the image index and its tag, {1} is the list of manifests digests @@ -161,7 +161,7 @@ Pushed image index '{0}' to registry '{1}'. - Pushed image index '{0}' to registry '{1}'. + イメージ インデックス '{0}' をレジストリ '{1}' にプッシュしました。 @@ -176,9 +176,14 @@ Cannot create manifest list (image index) because no images were provided. - Cannot create manifest list (image index) because no images were provided. + イメージが指定されていないため、マニフェスト リスト (イメージ インデックス) を作成できません。 + + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + {StrBegins="CONTAINER2031: "} + CONTAINER2015: {0}: '{1}' was not a valid Environment Variable. Ignoring. CONTAINER2015: {0}: '{1}' は有効な環境変数ではありませんでした。無視しています。 @@ -186,7 +191,7 @@ Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. - Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. + 指定されたイメージが無効なため、マニフェスト リスト (イメージ インデックス) を作成できません。項目には、'Config'、'Manifest'、'ManifestMediaType'、'ManifestDigest' のメタデータが必要です。 @@ -236,7 +241,7 @@ Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. - Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. + string[] TargetRuntimeIdentifiers が無効です。すべて 'linux-musl' または none のいずれかにする必要があります。 @@ -276,7 +281,7 @@ 'mediaType' of manifests should be the same in manifest list (image index). - 'mediaType' of manifests should be the same in manifest list (image index). + マニフェストの 'mediaType' は、マニフェストリスト (イメージ インデックス) で同じである必要があります。 @@ -416,7 +421,7 @@ Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. - Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. + 指定された 'mediaType' = '{0}' のマニフェスト リスト (イメージ インデックス) を作成できません。 diff --git a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.ko.xlf b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.ko.xlf index be9903c994e7..cbf4c28633b4 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.ko.xlf +++ b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.ko.xlf @@ -59,7 +59,7 @@ Building image index '{0}' on top of manifests {1}. - Building image index '{0}' on top of manifests {1}. + 매니페스트 {1} 위에 이미지 인덱스를 '{0}'. {0} is the name of the image index and its tag, {1} is the list of manifests digests @@ -161,7 +161,7 @@ Pushed image index '{0}' to registry '{1}'. - Pushed image index '{0}' to registry '{1}'. + '{0}' 이미지 인덱스를 '{1}' 레지스트리에 푸시했습니다. @@ -176,9 +176,14 @@ Cannot create manifest list (image index) because no images were provided. - Cannot create manifest list (image index) because no images were provided. + 제공된 이미지가 없으므로 매니페스트 목록(이미지 인덱스)을 만들 수 없습니다. + + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + {StrBegins="CONTAINER2031: "} + CONTAINER2015: {0}: '{1}' was not a valid Environment Variable. Ignoring. CONTAINER2015: {0}: '{1}'은(는) 유효한 환경 변수가 아닙니다. 무시 중. @@ -186,7 +191,7 @@ Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. - Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. + 제공된 이미지가 잘못되었으므로 매니페스트 목록(이미지 인덱스)을 만들 수 없습니다. 항목에는 'Config', 'Manifest', 'ManifestMediaType' 및 'ManifestDigest' 메타데이터가 있어야 합니다. @@ -236,7 +241,7 @@ Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. - Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. + 잘못된 string[] TargetRuntimeIdentifiers입니다. 모두 'linux-readl' 또는 none이어야 합니다. @@ -276,7 +281,7 @@ 'mediaType' of manifests should be the same in manifest list (image index). - 'mediaType' of manifests should be the same in manifest list (image index). + 매니페스트의 'mediaType'은 매니페스트 목록(이미지 인덱스)에서 같아야 합니다. @@ -416,7 +421,7 @@ Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. - Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. + 제공된 'mediaType' = '{0}' 대한 매니페스트 목록(이미지 인덱스)을 만들 수 없습니다. diff --git a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.pl.xlf b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.pl.xlf index 9a24297f33d2..7d7e97470018 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.pl.xlf +++ b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.pl.xlf @@ -59,7 +59,7 @@ Building image index '{0}' on top of manifests {1}. - Building image index '{0}' on top of manifests {1}. + Tworzenie '{0}' indeksu obrazu na górze manifestów {1}. {0} is the name of the image index and its tag, {1} is the list of manifests digests @@ -161,7 +161,7 @@ Pushed image index '{0}' to registry '{1}'. - Pushed image index '{0}' to registry '{1}'. + Wypchnięto indeks obrazu „{0}” do rejestru „{1}”. @@ -176,9 +176,14 @@ Cannot create manifest list (image index) because no images were provided. - Cannot create manifest list (image index) because no images were provided. + Nie można utworzyć listy manifestów (indeks obrazu), ponieważ nie podano obrazów. + + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + {StrBegins="CONTAINER2031: "} + CONTAINER2015: {0}: '{1}' was not a valid Environment Variable. Ignoring. CONTAINER2015: {0}: „{1}” nie jest prawidłową zmienną środowiskową. Ignorowanie. @@ -186,7 +191,7 @@ Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. - Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. + Nie można utworzyć listy manifestów (indeks obrazu), ponieważ podane obrazy są nieprawidłowe. Elementy muszą mieć metadane "Config", "Manifest", "ManifestMediaType" i "ManifestDigest". @@ -236,7 +241,7 @@ Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. - Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. + Nieprawidłowy element string[] TargetRuntimeIdentifiers. Wszystkie powinny mieć wartość "linux-musl" lub brak. @@ -276,7 +281,7 @@ 'mediaType' of manifests should be the same in manifest list (image index). - 'mediaType' of manifests should be the same in manifest list (image index). + Element "mediaType" manifestów powinien być taki sam na liście manifestów (indeks obrazu). @@ -416,7 +421,7 @@ Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. - Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. + Nie można utworzyć listy manifestów (indeks obrazu) dla podanego elementu "mediaType" = '{0}'. diff --git a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.pt-BR.xlf b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.pt-BR.xlf index 5d33fbd91e46..0fd4c0750417 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.pt-BR.xlf +++ b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.pt-BR.xlf @@ -59,7 +59,7 @@ Building image index '{0}' on top of manifests {1}. - Building image index '{0}' on top of manifests {1}. + Criando índice de '{0}' na parte superior dos manifestos {1}. {0} is the name of the image index and its tag, {1} is the list of manifests digests @@ -161,7 +161,7 @@ Pushed image index '{0}' to registry '{1}'. - Pushed image index '{0}' to registry '{1}'. + Índice de imagem enviada por push ''{0}'' para o registro ''{1}''. @@ -176,9 +176,14 @@ Cannot create manifest list (image index) because no images were provided. - Cannot create manifest list (image index) because no images were provided. + Não é possível criar a lista de manifestos (índice de imagem) porque nenhuma imagem foi fornecida. + + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + {StrBegins="CONTAINER2031: "} + CONTAINER2015: {0}: '{1}' was not a valid Environment Variable. Ignoring. CONTAINER2015: {0}: '{1}' não era uma variável de ambiente válida. Ignorando. @@ -186,7 +191,7 @@ Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. - Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. + Não é possível criar a lista de manifestos (índice de imagem) porque as imagens fornecidas são inválidas. Os itens devem ter metadados 'Config', 'Manifest', 'ManifestMediaType' e 'ManifestDigest'. @@ -236,7 +241,7 @@ Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. - Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. + Cadeia de caracteres inválida[] TargetRuntimeIdentifiers. Todos devem ser 'linux-musl' ou nenhum. @@ -276,7 +281,7 @@ 'mediaType' of manifests should be the same in manifest list (image index). - 'mediaType' of manifests should be the same in manifest list (image index). + 'mediaType' dos manifestos deve ser o mesmo na lista de manifestos (índice de imagem). @@ -416,7 +421,7 @@ Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. - Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. + Não é possível criar a lista de manifestos (índice de imagem) para o 'mediaType' = '{0}'. diff --git a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.ru.xlf b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.ru.xlf index 902bba0a69f1..a7e9356658d8 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.ru.xlf +++ b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.ru.xlf @@ -59,7 +59,7 @@ Building image index '{0}' on top of manifests {1}. - Building image index '{0}' on top of manifests {1}. + Построение индекса '{0}' поверх манифестов {1}. {0} is the name of the image index and its tag, {1} is the list of manifests digests @@ -161,7 +161,7 @@ Pushed image index '{0}' to registry '{1}'. - Pushed image index '{0}' to registry '{1}'. + Индекс изображения "{0}" отправлен в реестр "{1}". @@ -176,9 +176,14 @@ Cannot create manifest list (image index) because no images were provided. - Cannot create manifest list (image index) because no images were provided. + Не удается создать список манифестов (индекс образа), так как изображения не предоставлены. + + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + {StrBegins="CONTAINER2031: "} + CONTAINER2015: {0}: '{1}' was not a valid Environment Variable. Ignoring. CONTAINER2015: {0}: "{1}" не является допустимой переменной среды. Пропуск. @@ -186,7 +191,7 @@ Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. - Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. + Не удается создать список манифестов (индекс образа), так как предоставленные образы недопустимы. Элементы должны иметь метаданные "Config", "Manifest", "ManifestMediaType" и "ManifestDigest". @@ -236,7 +241,7 @@ Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. - Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. + Недопустимая строка[] TargetRuntimeIdentifiers. Все должны быть либо "linux-маскали", либо нет. @@ -276,7 +281,7 @@ 'mediaType' of manifests should be the same in manifest list (image index). - 'mediaType' of manifests should be the same in manifest list (image index). + MediaType манифестов должен быть одинаковым в списке манифестов (индексе образа). @@ -416,7 +421,7 @@ Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. - Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. + Не удается создать список манифестов (индекс образа) для указанного "mediaType" = '{0}'. diff --git a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.tr.xlf b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.tr.xlf index 605c9bdda808..3e80453768be 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.tr.xlf +++ b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.tr.xlf @@ -59,7 +59,7 @@ Building image index '{0}' on top of manifests {1}. - Building image index '{0}' on top of manifests {1}. + Bildirim listesi '{0}' görüntü dizini {1}. {0} is the name of the image index and its tag, {1} is the list of manifests digests @@ -161,7 +161,7 @@ Pushed image index '{0}' to registry '{1}'. - Pushed image index '{0}' to registry '{1}'. + '{0}' görüntü dizini '{1}' kayıt defterine gönderildi. @@ -176,9 +176,14 @@ Cannot create manifest list (image index) because no images were provided. - Cannot create manifest list (image index) because no images were provided. + Hiçbir görüntü sağlanmadığından bildirim listesi (görüntü dizini) oluşturulamıyor. + + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + {StrBegins="CONTAINER2031: "} + CONTAINER2015: {0}: '{1}' was not a valid Environment Variable. Ignoring. CONTAINER2015: {0}: '{1}' geçerli bir Ortam Değişkeni değildi. Görmezden geliniyor. @@ -186,7 +191,7 @@ Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. - Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. + Sağlanan görüntüler geçersiz olduğundan bildirim listesi (görüntü dizini) oluşturulamıyor. Öğeler 'Config', 'Manifest', 'ManifestMediaType' ve 'ManifestDigest' meta verilerine sahip olmalıdır. @@ -236,7 +241,7 @@ Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. - Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. + Geçersiz string[] TargetRuntimeIdentifiers. Tümü 'linux-musl' veya hiçbiri olmalıdır. @@ -276,7 +281,7 @@ 'mediaType' of manifests should be the same in manifest list (image index). - 'mediaType' of manifests should be the same in manifest list (image index). + Bildirim listesinde (görüntü dizini) bildirimlerin 'mediaType' değeri aynı olmalıdır. @@ -416,7 +421,7 @@ Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. - Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. + Sağlanan 'mediaType' = '{0}' için bildirim listesi (görüntü dizini) oluşturulamıyor. diff --git a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.zh-Hans.xlf b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.zh-Hans.xlf index 0477091274c0..2c3f4e2171f3 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.zh-Hans.xlf @@ -59,7 +59,7 @@ Building image index '{0}' on top of manifests {1}. - Building image index '{0}' on top of manifests {1}. + 在清单 {1} 顶部生成图像索引 '{0}'。 {0} is the name of the image index and its tag, {1} is the list of manifests digests @@ -161,7 +161,7 @@ Pushed image index '{0}' to registry '{1}'. - Pushed image index '{0}' to registry '{1}'. + 已将映像索引“{0}”推送到注册表“{1}”。 @@ -176,9 +176,14 @@ Cannot create manifest list (image index) because no images were provided. - Cannot create manifest list (image index) because no images were provided. + 无法 (映像索引) 创建清单列表,因为未提供映像。 + + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + {StrBegins="CONTAINER2031: "} + CONTAINER2015: {0}: '{1}' was not a valid Environment Variable. Ignoring. CONTAINER2015: {0}: "{1}" 不是有效的环境变量。忽略。 @@ -186,7 +191,7 @@ Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. - Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. + 无法 (映像索引) 创建清单列表,因为提供的映像无效。项必须具有 “Config”、“Manifest”、“ManifestMediaType” 和 “ManifestDigest” 元数据。 @@ -236,7 +241,7 @@ Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. - Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. + 无效的 string[] TargetRuntimeIdentifiers。全部应为 “linux-musl” 或无。 @@ -276,7 +281,7 @@ 'mediaType' of manifests should be the same in manifest list (image index). - 'mediaType' of manifests should be the same in manifest list (image index). + 清单的 “mediaType” 在清单列表 (映像索引) 中应相同。 @@ -416,7 +421,7 @@ Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. - Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. + 无法为提供的 “mediaType” = '{0}' 创建清单列表 (映像索引)。 diff --git a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.zh-Hant.xlf b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.zh-Hant.xlf index bc58505af2bc..5ad488338f97 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.zh-Hant.xlf @@ -59,7 +59,7 @@ Building image index '{0}' on top of manifests {1}. - Building image index '{0}' on top of manifests {1}. + 正在將映像索引 '{0}' 在指令清單頂端 {1}。 {0} is the name of the image index and its tag, {1} is the list of manifests digests @@ -161,7 +161,7 @@ Pushed image index '{0}' to registry '{1}'. - Pushed image index '{0}' to registry '{1}'. + 已將影像 '{0}' 推送至登錄 '{1}'。 @@ -176,9 +176,14 @@ Cannot create manifest list (image index) because no images were provided. - Cannot create manifest list (image index) because no images were provided. + 無法建立映射索引) (指令清單清單,因為未提供影像。 + + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + CONTAINER2031: The container image format '{0}' is not supported. Supported formats are '{1}'. + {StrBegins="CONTAINER2031: "} + CONTAINER2015: {0}: '{1}' was not a valid Environment Variable. Ignoring. CONTAINER2015: {0}: '{1}' 不是有效的環境變數。正在忽略。 @@ -186,7 +191,7 @@ Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. - Cannot create manifest list (image index) because provided images are invalid. Items must have 'Config', 'Manifest', 'ManifestMediaType' and 'ManifestDigest' metadata. + 無法建立 (映射索引) 的指令清單清單,因為提供的映像無效。項目必須有 'Config'、'Manifest'、'ManifestMediaType' 和 'ManifestDigest' 元數據。 @@ -236,7 +241,7 @@ Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. - Invalid string[] TargetRuntimeIdentifiers. Either all should be 'linux-musl' or none. + 無效的字串[] TargetRuntimeIdentifiers。全部應為 『linux-musl』 或無。 @@ -276,7 +281,7 @@ 'mediaType' of manifests should be the same in manifest list (image index). - 'mediaType' of manifests should be the same in manifest list (image index). + 指令清單的 'mediaType' 在指令清單清單 (映射索引) 中必須相同。 @@ -416,7 +421,7 @@ Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. - Cannot create manifest list (image index) for the provided 'mediaType' = '{0}'. + 無法為提供的 'mediaType' = '{0}' 建立映射索引) (指令清單清單。 diff --git a/src/Containers/Microsoft.NET.Build.Containers/Tasks/CreateNewImage.Interface.cs b/src/Containers/Microsoft.NET.Build.Containers/Tasks/CreateNewImage.Interface.cs index 461ba622ccfc..f30de87ceb38 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Tasks/CreateNewImage.Interface.cs +++ b/src/Containers/Microsoft.NET.Build.Containers/Tasks/CreateNewImage.Interface.cs @@ -166,6 +166,11 @@ partial class CreateNewImage [Required] public bool GenerateDigestLabel { get; set; } + /// + /// Set to either 'OCI', 'Docker', or null. If unset, the generated images' mediaType will be that of the base image. If set, the generated image will be given the specified media type. + /// + public string? ImageFormat { get; set; } + [Output] public string GeneratedContainerManifest { get; set; } diff --git a/src/Containers/Microsoft.NET.Build.Containers/Tasks/CreateNewImage.cs b/src/Containers/Microsoft.NET.Build.Containers/Tasks/CreateNewImage.cs index 4d81b963f4a7..19e0cac692d4 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Tasks/CreateNewImage.cs +++ b/src/Containers/Microsoft.NET.Build.Containers/Tasks/CreateNewImage.cs @@ -124,6 +124,24 @@ internal async Task ExecuteAsync(CancellationToken cancellationToken) SafeLog(Strings.ContainerBuilder_StartBuildingImage, Repository, string.Join(",", ImageTags), sourceImageReference); + // forcibly change the media type if required + if (ImageFormat is not null) + { + if (Enum.TryParse(ImageFormat, out var imageFormat)) + { + imageBuilder.ManifestMediaType = imageFormat switch + { + KnownImageFormats.Docker => SchemaTypes.DockerManifestV2, + KnownImageFormats.OCI => SchemaTypes.OciManifestV1, + _ => imageBuilder.ManifestMediaType // should be impossible unless we add to the enum + }; + } + else + { + Log.LogErrorWithCodeFromResources(nameof(Strings.InvalidContainerImageFormat), ImageFormat, string.Join(",", Enum.GetValues())); + } + } + Layer newLayer = Layer.FromDirectory(PublishDirectory, WorkingDirectory, imageBuilder.IsWindows, imageBuilder.ManifestMediaType); imageBuilder.AddLayer(newLayer); imageBuilder.SetWorkingDirectory(WorkingDirectory); diff --git a/src/Containers/Microsoft.NET.Build.Containers/Tasks/CreateNewImageToolTask.cs b/src/Containers/Microsoft.NET.Build.Containers/Tasks/CreateNewImageToolTask.cs index c1bc8fc24af8..90bf398c900b 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Tasks/CreateNewImageToolTask.cs +++ b/src/Containers/Microsoft.NET.Build.Containers/Tasks/CreateNewImageToolTask.cs @@ -123,6 +123,10 @@ internal string GenerateCommandLineCommandsInt() { builder.AppendSwitchIfNotNull("--appcommandinstruction ", AppCommandInstruction); } + if (!string.IsNullOrWhiteSpace(ImageFormat)) + { + builder.AppendSwitchIfNotNull("--image-format ", ImageFormat); + } AppendSwitchIfNotNullSanitized(builder, "--entrypoint ", nameof(Entrypoint), Entrypoint); AppendSwitchIfNotNullSanitized(builder, "--entrypointargs ", nameof(EntrypointArgs), EntrypointArgs); diff --git a/src/Containers/containerize/ContainerizeCommand.cs b/src/Containers/containerize/ContainerizeCommand.cs index fd47e728142c..612b589ba7fd 100644 --- a/src/Containers/containerize/ContainerizeCommand.cs +++ b/src/Containers/containerize/ContainerizeCommand.cs @@ -203,6 +203,11 @@ internal class ContainerizeCommand : CliRootCommand Arity = ArgumentArity.Zero }; + internal CliOption ImageFormatOption { get; } = new("--image-format") + { + Description = "If set to OCI or Docker will force the generated image to be that format. If unset, the base images format will be used." + }; + internal ContainerizeCommand() : base("Containerize an application without Docker.") { PublishDirectoryArgument.AcceptLegalFilePathsOnly(); @@ -232,6 +237,7 @@ internal ContainerizeCommand() : base("Containerize an application without Docke Options.Add(ContainerUserOption); Options.Add(GenerateLabelsOption); Options.Add(GenerateDigestLabelOption); + Options.Add(ImageFormatOption); SetAction(async (parseResult, cancellationToken) => { @@ -260,6 +266,7 @@ internal ContainerizeCommand() : base("Containerize an application without Docke string? _containerUser = parseResult.GetValue(ContainerUserOption); bool _generateLabels = parseResult.GetValue(GenerateLabelsOption); bool _generateDigestLabel = parseResult.GetValue(GenerateDigestLabelOption); + KnownImageFormats? _imageFormat = parseResult.GetValue(ImageFormatOption); //setup basic logging bool traceEnabled = Env.GetEnvironmentVariableAsBool("CONTAINERIZE_TRACE_LOGGING_ENABLED"); @@ -292,6 +299,7 @@ await ContainerBuilder.ContainerizeAsync( _archiveOutputPath, _generateLabels, _generateDigestLabel, + _imageFormat, loggerFactory, cancellationToken).ConfigureAwait(false); }); diff --git a/src/Containers/packaging/build/Microsoft.NET.Build.Containers.targets b/src/Containers/packaging/build/Microsoft.NET.Build.Containers.targets index 50458adc2a37..351099cbd6c6 100644 --- a/src/Containers/packaging/build/Microsoft.NET.Build.Containers.targets +++ b/src/Containers/packaging/build/Microsoft.NET.Build.Containers.targets @@ -34,10 +34,10 @@ - $(RuntimeIdentifiers) - $(RuntimeIdentifier) + $(RuntimeIdentifier) + $(RuntimeIdentifiers) linux-$(NETCoreSdkPortableRuntimeIdentifier.Split('-')[1]) <_ContainerIsUsingMicrosoftDefaultImages Condition="'$(ContainerBaseImage)' == ''">true @@ -45,8 +45,8 @@ - <_TargetRuntimeIdentifiers Include="$(ContainerRuntimeIdentifiers)" Condition="'$(ContainerRuntimeIdentifiers)' != ''" /> - <_TargetRuntimeIdentifiers Include="$(ContainerRuntimeIdentifier)" Condition="'$(ContainerRuntimeIdentifiers)' == ''" /> + <_TargetRuntimeIdentifiers Include="$(ContainerRuntimeIdentifier)" Condition="'$(ContainerRuntimeIdentifier)' != ''" /> + <_TargetRuntimeIdentifiers Include="$(ContainerRuntimeIdentifiers)" Condition="@(_TargetRuntimeIdentifiers->Count()) == 0" /> @@ -400,7 +401,14 @@ Condition="'$(IsPublishable)' == 'true' AND '$(EnableSdkContainerSupport)' == 'true'"> <_IsMultiTFMBuild Condition="'$(TargetFrameworks)' != '' and '$(TargetFramework)' == ''">true - <_IsMultiRIDBuild Condition="'$(BuildingInsideVisualStudio)' != 'true' and (('$(RuntimeIdentifiers)' != '' and '$(RuntimeIdentifier)' == '') or ('$(ContainerRuntimeIdentifiers)' != '' and '$(ContainerRuntimeIdentfier)' == ''))">true + + <_HasCRIDsAndNoCRID Condition="'$(ContainerRuntimeIdentifiers)' != '' and '$(ContainerRuntimeIdentifier)' == ''">true + <_HasRIDs Condition="'$(RuntimeIdentifiers)' != ''">true + <_NoCRIDsOrCRIDorRID Condition="'$(ContainerRuntimeIdentifiers)' == '' and '$(ContainerRuntimeIdentifier)' == '' and '$(RuntimeIdentifier)' == ''">true + <_IsMultiRIDBuild Condition="'$(BuildingInsideVisualStudio)' != 'true' and ('$(_HasCRIDsAndNoCRID)' == true or ('$(_HasRIDs)' == 'true' and '$(_NoCRIDsOrCRIDorRID)' == 'true'))">true <_IsSingleRIDBuild Condition="'$(_IsMultiRIDBuild)' == ''">true diff --git a/src/Installer/redist-installer/targets/GenerateBundledVersions.targets b/src/Installer/redist-installer/targets/GenerateBundledVersions.targets index 3d0600418a92..bdd03fe54465 100644 --- a/src/Installer/redist-installer/targets/GenerateBundledVersions.targets +++ b/src/Installer/redist-installer/targets/GenerateBundledVersions.targets @@ -239,9 +239,15 @@ linux-musl-loongarch64; " /> + + - + - $(NetRuntimeRid) - $(Architecture) - $(OSName)-$(InstallerTargetArchitecture) - rhel.7-aarch64 - x64 x86 dotnet-host$(InstallerStartSuffix)-$(SharedHostVersion)-$(SharedFrameworkInstallerFileRid)$(InstallerExtension) dotnet-hostfxr$(InstallerStartSuffix)-$(HostFxrVersion)-$(SharedFrameworkInstallerFileRid)$(InstallerExtension) dotnet-runtime$(InstallerStartSuffix)-$(MicrosoftNETCoreAppRuntimePackageVersion)-$(SharedFrameworkInstallerFileRid)$(InstallerExtension) dotnet-runtime$(InstallerStartSuffix)$(PgoTerm)-$(VSRedistCommonNetCoreSharedFrameworkx64100PackageVersion)-$(SharedFrameworkInstallerFileRid)$(InstallerExtension) - dotnet-runtime-deps-$(SharedHostVersion)-$(RuntimeDepsInstallerFileRid)$(InstallerExtension) windowsdesktop-runtime-$(MicrosoftWindowsDesktopAppRuntimePackageVersion)-$(SharedFrameworkInstallerFileRid)$(InstallerExtension) dotnet-targeting-pack-$(MicrosoftNETCoreAppRefPackageVersion)-$(SharedFrameworkInstallerFileRid)$(InstallerExtension) dotnet-apphost-pack-$(MicrosoftNETCoreAppHostPackageVersion)-$(SharedFrameworkInstallerFileRid)$(InstallerExtension) @@ -209,12 +202,6 @@ - - $(NetRuntimeRootUrl) - $(DownloadedRuntimeDepsInstallerFileName) - - $(NetRuntimeRootUrl) diff --git a/src/Layout/redist/minimumMSBuildVersion b/src/Layout/redist/minimumMSBuildVersion index 903f9e3b78b3..c9c79bfca0a9 100644 --- a/src/Layout/redist/minimumMSBuildVersion +++ b/src/Layout/redist/minimumMSBuildVersion @@ -1 +1 @@ -17.11.0 +17.12.0 diff --git a/src/Layout/redist/targets/GenerateArchive.targets b/src/Layout/redist/targets/GenerateArchive.targets index a67bd7a4b70c..8badfdee7ef9 100644 --- a/src/Layout/redist/targets/GenerateArchive.targets +++ b/src/Layout/redist/targets/GenerateArchive.targets @@ -14,8 +14,6 @@ $(ArtifactNameSdk)-$(Version) $(ArtifactNameSdkLanguagePack)-$(Version) - - $(ArtifactsBinDir)version.txt - - diff --git a/src/Layout/redist/targets/GenerateLayout.targets b/src/Layout/redist/targets/GenerateLayout.targets index 3160feb51095..5cfe9d673031 100644 --- a/src/Layout/redist/targets/GenerateLayout.targets +++ b/src/Layout/redist/targets/GenerateLayout.targets @@ -177,7 +177,7 @@ - netcoreapp3.1 + net9.0 $(NetCurrent) net9.0 $(NuGetPackageRoot)/microsoft.testplatform.cli/$(MicrosoftTestPlatformCLIPackageVersion)/contentFiles/any/$(TestCliNuGetDirectoryTargetFramework)/ diff --git a/src/RazorSdk/Tool/CompositeRazorProjectFileSystem.cs b/src/RazorSdk/Tool/CompositeRazorProjectFileSystem.cs index e13acaf1b922..72312aeffecc 100644 --- a/src/RazorSdk/Tool/CompositeRazorProjectFileSystem.cs +++ b/src/RazorSdk/Tool/CompositeRazorProjectFileSystem.cs @@ -27,11 +27,6 @@ public override IEnumerable EnumerateItems(string basePath) } } - public override RazorProjectItem GetItem(string path) - { - return GetItem(path, fileKind: null); - } - public override RazorProjectItem GetItem(string path, string fileKind) { RazorProjectItem razorProjectItem = null; diff --git a/src/RazorSdk/Tool/GenerateCommand.cs b/src/RazorSdk/Tool/GenerateCommand.cs index 33a83f3f4e5b..41deeac0fa2e 100644 --- a/src/RazorSdk/Tool/GenerateCommand.cs +++ b/src/RazorSdk/Tool/GenerateCommand.cs @@ -257,7 +257,7 @@ private int ExecuteCore( { // Only output the file if we generated it without errors. var outputFilePath = result.InputItem.OutputPath; - var generatedCode = result.CSharpDocument.GeneratedCode; + var generatedCode = result.CSharpDocument.Text.ToString(); if (isGeneratingDeclaration) { // When emiting declarations, only write if it the contents are different. @@ -269,7 +269,7 @@ private int ExecuteCore( } } - File.WriteAllText(outputFilePath, result.CSharpDocument.GeneratedCode); + File.WriteAllText(outputFilePath, generatedCode); } } @@ -399,10 +399,8 @@ public SourceItem(string sourcePath, string outputPath, string physicalRelativeP public string CssScope { get; } } - private class StaticTagHelperFeature : ITagHelperFeature + private class StaticTagHelperFeature : RazorEngineFeatureBase, ITagHelperFeature { - public RazorEngine Engine { get; set; } - public IReadOnlyList TagHelpers { get; set; } public IReadOnlyList GetDescriptors() => TagHelpers; diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifest.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifest.cs index 80f2ad7f662b..f4181dc59829 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifest.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifest.cs @@ -47,5 +47,7 @@ internal WorkloadManifest(string id, FXVersion version, string? description, str public Dictionary Workloads { get; } public Dictionary Packs { get; } - } + + public static WorkloadManifest CreateForTests(string id) => new(id, new FXVersion(7, 3, 5), null, string.Empty, [], [], []); +} } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadSuggestionFinder.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadSuggestionFinder.cs index 3056d7dde8a4..8fdcc00b2516 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadSuggestionFinder.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadSuggestionFinder.cs @@ -187,6 +187,7 @@ private static T FindBest(IEnumerable values, params Comparison[] compa internal static WorkloadSuggestion GetBestSuggestion(ICollection suggestions) => FindBest( suggestions, + (x, y) => ContainsExperimental(y.Workloads) - ContainsExperimental(x.Workloads), (x, y) => y.ExtraPacks - x.ExtraPacks, (x, y) => y.Workloads.Count - x.Workloads.Count); @@ -195,6 +196,8 @@ internal static WorkloadSuggestion GetBestSuggestion(ICollection public WorkloadSuggestion GetBestSuggestion() => GetBestSuggestion(UnsortedSuggestions); + private static int ContainsExperimental(HashSet set) => set.Any(w => w.ToString().Contains("experimental")) ? 1 : 0; + /// /// A partial or complete suggestion for workloads to install, annotated with which requested packs it does not satisfy /// diff --git a/src/SourceBuild/content/Directory.Build.props b/src/SourceBuild/content/Directory.Build.props index 0060e99dd227..6885572957d1 100644 --- a/src/SourceBuild/content/Directory.Build.props +++ b/src/SourceBuild/content/Directory.Build.props @@ -31,12 +31,8 @@ true true true - - true - true - - true + true runtime @@ -168,11 +164,11 @@ $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'toolset', 'VSSdkResolvers')) $([MSBuild]::NormalizeDirectory('$(ArtifactsObjDir)', 'Symbols')) - + $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'manifests', '$(Configuration)')) $([MSBuild]::NormalizeDirectory('$(ArtifactsObjDir)', 'manifests', '$(Configuration)')) $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'assets', '$(Configuration)')) - + $([MSBuild]::NormalizeDirectory('$(ArtifactsObjDir)', 'extracted-dotnet-sdk')) $([MSBuild]::NormalizeDirectory('$(PrereqsPackagesDir)', 'prebuilt')) @@ -180,8 +176,6 @@ $([MSBuild]::NormalizeDirectory('$(PrereqsPackagesDir)', 'previously-source-built')) $([MSBuild]::EnsureTrailingSlash('$(CustomPrebuiltSourceBuiltPackagesPath)')) - $([MSBuild]::NormalizeDirectory('$(PrereqsDir)', 'git-info')) - $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'prebuilt-report')) $([MSBuild]::NormalizeDirectory('$(PackageReportDir)', 'prebuilt-packages')) $([MSBuild]::NormalizeDirectory('$(SrcDir)', 'source-build-reference-packages', 'src')) diff --git a/src/SourceBuild/content/Directory.Build.targets b/src/SourceBuild/content/Directory.Build.targets index fde76356c705..183f0d154973 100644 --- a/src/SourceBuild/content/Directory.Build.targets +++ b/src/SourceBuild/content/Directory.Build.targets @@ -45,7 +45,6 @@ Inputs="@(BinPlaceDir);%(BinPlaceDir.Identity)" Outputs="unused"> - true <_BinPlaceDir>%(BinPlaceDir.Identity) @@ -62,7 +61,7 @@ OverwriteReadOnlyFiles="true" Retries="$(CopyRetryCount)" RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)" - UseHardlinksIfPossible="$(BinPlaceUseHardlinksIfPossible)" /> + UseHardlinksIfPossible="true" /> diff --git a/src/SourceBuild/content/README.md b/src/SourceBuild/content/README.md index ec2db00153e6..36f39876cfaa 100644 --- a/src/SourceBuild/content/README.md +++ b/src/SourceBuild/content/README.md @@ -77,6 +77,14 @@ For the latest information about Source-Build support, please watch for announce The dependencies for building can be found [here](https://github.com/dotnet/runtime/blob/main/docs/workflow/requirements/). In case you don't want to / cannot prepare your environment per the requirements, consider [using Docker](#building-using-docker). +For building the VMR on Windows, it is recommended to put the repo under a short path, i.e. `C:\dotnet`. Also, [long path support must be enabled](https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry#enable-long-paths-in-windows-10-version-1607-and-later). This is necessary as some of the tools used don't support long paths (WiX Toolset v3 and cl.exe). + +For some `git` commands and when synchronizing changes via the `darc` CLI, long path support should be enabled in the `git` config as well: +```bash +git config --system core.longpaths true # needs elevated prompt +git config --global core.longpaths true +``` + ### Building 1. **Clone the repository** diff --git a/src/SourceBuild/content/build.sh b/src/SourceBuild/content/build.sh index 513c7fc7f6c5..a50ec66485b1 100755 --- a/src/SourceBuild/content/build.sh +++ b/src/SourceBuild/content/build.sh @@ -37,8 +37,6 @@ usage() echo "Non-source-only settings:" echo " --build-repo-tests Build repository tests" - echo " --dev Use -dev or -ci versioning instead of .NET official build versions" - echo "Advanced settings:" echo " --ci Set when running on CI server" @@ -89,7 +87,6 @@ packagesPreviouslySourceBuiltDir="${packagesDir}previously-source-built/" ci=false exclude_ci_binary_log=false prepare_machine=false -use_dev_versioning=false target_rid= system_libs= @@ -196,9 +193,6 @@ while [[ $# > 0 ]]; do -use-mono-runtime) properties+=( "/p:DotNetBuildUseMonoRuntime=true" ) ;; - -dev) - use_dev_versioning=true - ;; *) properties+=( "$1" ) ;; @@ -213,10 +207,6 @@ if [[ "$ci" == true ]]; then fi fi -if [[ "$use_dev_versioning" == true && "$sourceOnly" != true ]]; then - properties+=( "/p:UseOfficialBuildVersioning=false" ) -fi - # Never use the global nuget cache folder use_global_nuget_cache=false diff --git a/src/SourceBuild/content/eng/Version.Details.xml b/src/SourceBuild/content/eng/Version.Details.xml index d3c0c969ed1b..809c1a92f7b2 100644 --- a/src/SourceBuild/content/eng/Version.Details.xml +++ b/src/SourceBuild/content/eng/Version.Details.xml @@ -2,9 +2,9 @@ - + https://github.com/dotnet/arcade - f2135575461b9adce73a7178f0a9692c2b8608f1 + fe17712bedb95a55d5af00c5191772c81393745f diff --git a/src/SourceBuild/content/eng/Versions.props b/src/SourceBuild/content/eng/Versions.props index 7166b6cfe082..62928dd47dd9 100644 --- a/src/SourceBuild/content/eng/Versions.props +++ b/src/SourceBuild/content/eng/Versions.props @@ -23,8 +23,8 @@ of a .NET major or minor release, prebuilts may be needed. When the release is mature, prebuilts are not necessary, and this property is removed from the file. --> - 10.0.100-alpha.1.25061.1 - 10.0.100-alpha.1.25061.1 + 10.0.100-preview.1.25078.1 + 10.0.100-preview.1.25078.1 2.0.0-beta4.24126.1 diff --git a/src/SourceBuild/content/eng/build.ps1 b/src/SourceBuild/content/eng/build.ps1 index 554be1de99bb..c91bc6d56a3d 100644 --- a/src/SourceBuild/content/eng/build.ps1 +++ b/src/SourceBuild/content/eng/build.ps1 @@ -17,7 +17,6 @@ Param( [switch][Alias('cwb')]$cleanWhileBuilding, [switch][Alias('nobl')]$excludeCIBinarylog, [switch] $prepareMachine, - [switch] $dev, [Parameter(ValueFromRemainingArguments=$true)][String[]]$properties ) @@ -41,7 +40,6 @@ function Get-Usage() { Write-Host " -cleanWhileBuilding Cleans each repo after building (reduces disk space usage, short: -cwb)" Write-Host " -excludeCIBinarylog Don't output binary log (short: -nobl)" Write-Host " -prepareMachine Prepare machine for CI run, clean up processes after build" - Write-Host " -dev Use -dev or -ci versioning instead of .NET official build versions" Write-Host "" } @@ -78,10 +76,6 @@ if ($cleanWhileBuilding) { $arguments += "/p:CleanWhileBuilding=true" } -if ($dev) { - $arguments += "/p:UseOfficialBuildVersioning=false" -} - function Build { InitializeToolset diff --git a/src/SourceBuild/content/eng/finish-source-only.proj b/src/SourceBuild/content/eng/finish-source-only.proj index df0ef28dde91..bd569ab83db6 100644 --- a/src/SourceBuild/content/eng/finish-source-only.proj +++ b/src/SourceBuild/content/eng/finish-source-only.proj @@ -25,8 +25,13 @@ + + + + + diff --git a/src/SourceBuild/content/eng/init-source-only.proj b/src/SourceBuild/content/eng/init-source-only.proj index 5979f251d5e4..baa4bbe720ee 100644 --- a/src/SourceBuild/content/eng/init-source-only.proj +++ b/src/SourceBuild/content/eng/init-source-only.proj @@ -56,6 +56,9 @@ + + + $(NetCurrent) - + @@ -19,15 +19,15 @@ - + - + Exclude="$(VerticalManifestsPath)\*Shortstack*.xml" /> - + - - - \ No newline at end of file + + diff --git a/src/SourceBuild/content/eng/pipelines/ci.yml b/src/SourceBuild/content/eng/pipelines/ci.yml index b90953c3b857..6f3a8255fef7 100644 --- a/src/SourceBuild/content/eng/pipelines/ci.yml +++ b/src/SourceBuild/content/eng/pipelines/ci.yml @@ -29,6 +29,16 @@ # - PR: lite build # - CI: release/*, internal/release/* and main only, every batched commit, full build +parameters: +- name: desiredSigning + displayName: 'Sign?' + type: string + default: 'Default (unsigned for manual and non-main/release builds)' + values: + - Signed + - Unsigned + - Default (unsigned for manual and non-main/release builds) + variables: # enable source-only build for pipelines that contain the -source-build string - name: isSourceOnlyBuild @@ -43,6 +53,13 @@ variables: - name: isPRTrigger value: ${{ eq(variables['Build.Reason'], 'PullRequest') }} +- ${{ if eq(variables['System.TeamProject'], 'public') }}: + - name: skipComponentGovernanceDetection # we run CG on internal builds only + value: true + + - name: Codeql.Enabled # we run CodeQL on internal builds only + value: false + - template: /eng/common/templates-official/variables/pool-providers.yml@self - template: /src/sdk/eng/pipelines/templates/variables/vmr-build.yml@self @@ -103,14 +120,14 @@ extends: ${{ variables.azurelinuxArm64CrossContainerName }}: image: ${{ variables.azurelinuxArm64CrossContainerImage }} options: ${{ variables.defaultContainerOptions }} - ${{ variables.azurelinuxX64AlpineCrossContainerName }}: - image: ${{ variables.azurelinuxX64AlpineCrossContainerImage }} + ${{ variables.azurelinuxX64MuslCrossContainerName }}: + image: ${{ variables.azurelinuxX64MuslCrossContainerImage }} options: ${{ variables.defaultContainerOptions }} - ${{ variables.azurelinuxArmAlpineCrossContainerName }}: - image: ${{ variables.azurelinuxArmAlpineCrossContainerImage }} + ${{ variables.azurelinuxArmMuslCrossContainerName }}: + image: ${{ variables.azurelinuxArmMuslCrossContainerImage }} options: ${{ variables.defaultContainerOptions }} - ${{ variables.azurelinuxArm64AlpineCrossContainerName }}: - image: ${{ variables.azurelinuxArm64AlpineCrossContainerImage }} + ${{ variables.azurelinuxArm64MuslCrossContainerName }}: + image: ${{ variables.azurelinuxArm64MuslCrossContainerImage }} options: ${{ variables.defaultContainerOptions }} ${{ variables.androidCrossContainerName }}: image: ${{ variables.androidCrossContainerImage }} diff --git a/src/SourceBuild/content/eng/pipelines/pr.yml b/src/SourceBuild/content/eng/pipelines/pr.yml index 471f6a92b751..ab4e3f3d7db7 100644 --- a/src/SourceBuild/content/eng/pipelines/pr.yml +++ b/src/SourceBuild/content/eng/pipelines/pr.yml @@ -13,6 +13,9 @@ # - CI: release/* only, every batched commit, full build # - Schedule: main only, full build # +# - dotnet-unified-build-full (public) +# https://dev.azure.com/dnceng-public/public/_build?definitionId=303 +# Comment trigger only variables: # enable source-only build for pipelines that contain the -source-build string @@ -28,8 +31,12 @@ variables: - name: isPRTrigger value: ${{ eq(variables['Build.Reason'], 'PullRequest') }} -- name: Codeql.Enabled # we run CodeQL on internal builds only - value: false +- ${{ if eq(variables['System.TeamProject'], 'public') }}: + - name: skipComponentGovernanceDetection # we run CG on internal builds only + value: true + + - name: Codeql.Enabled # we run CodeQL on internal builds only + value: false - template: /eng/common/templates/variables/pool-providers.yml@self @@ -38,7 +45,7 @@ stages: parameters: isBuiltFromVmr: true isSourceOnlyBuild: ${{ variables.isSourceOnlyBuild }} - ${{ if eq(variables.isScheduleTrigger, 'true') }}: + ${{ if or(eq(variables.isScheduleTrigger, 'true'), contains(variables['Build.DefinitionName'], '-full')) }}: scope: full ${{ elseif eq(variables.isSourceOnlyBuildLite, 'true') }}: scope: lite diff --git a/src/SourceBuild/content/eng/tools/tasks/Microsoft.DotNet.UnifiedBuild.Tasks/WriteSbrpUsageReport.cs b/src/SourceBuild/content/eng/tools/tasks/Microsoft.DotNet.UnifiedBuild.Tasks/WriteSbrpUsageReport.cs index 49a7f8213069..baf653674960 100644 --- a/src/SourceBuild/content/eng/tools/tasks/Microsoft.DotNet.UnifiedBuild.Tasks/WriteSbrpUsageReport.cs +++ b/src/SourceBuild/content/eng/tools/tasks/Microsoft.DotNet.UnifiedBuild.Tasks/WriteSbrpUsageReport.cs @@ -31,10 +31,12 @@ public class WriteSbrpUsageReport : Task public required string SbrpRepoSrcPath { get; set; } /// - /// Path to the VMR src directory. + /// Paths to the project.assets.json files produced by the build. + /// + /// %(Identity): project.assets.json file path. /// [Required] - public required string SrcPath { get; set; } + public required ITaskItem[] ProjectAssetsJsons { get; set; } /// /// Path to the usage report to. @@ -61,6 +63,12 @@ private void GenerateUsageReport() PackageInfo[] existingSbrps = [.. _sbrpPackages.Values.OrderBy(pkg => pkg.Id)]; PurgeNonReferencedReferences(); IEnumerable unreferencedSbrps = GetUnreferencedSbrps().Select(pkg => pkg.Path).OrderBy(id => id); + + if (unreferencedSbrps.Count() == existingSbrps.Length) + { + Log.LogError("No SBRP packages are detected as being referenced."); + } + Report report = new(existingSbrps, unreferencedSbrps); string reportFilePath = Path.Combine(OutputPath, "sbrpPackageUsage.json"); @@ -144,7 +152,13 @@ private void ReadSbrpPackages(string packageType, bool trackTfms) private void ScanProjectReferences() { - foreach (string projectJsonFile in Directory.GetFiles(SrcPath, "project.assets.json", SearchOption.AllDirectories)) + if (ProjectAssetsJsons.Length == 0) + { + Log.LogError($"No project.assets.json files were specified."); + return; + } + + foreach (string projectJsonFile in ProjectAssetsJsons.Select(item => item.GetMetadata("Identity"))) { LockFile lockFile = new LockFileFormat().Read(projectJsonFile); foreach (LockFileTargetLibrary lib in lockFile.Targets.SelectMany(t => t.Libraries)) diff --git a/src/SourceBuild/content/global.json b/src/SourceBuild/content/global.json index 990027d87c4f..5668264000d8 100644 --- a/src/SourceBuild/content/global.json +++ b/src/SourceBuild/content/global.json @@ -1,10 +1,10 @@ { "tools": { - "dotnet": "10.0.100-alpha.1.25061.2" + "dotnet": "10.0.100-preview.1.25078.4" }, "msbuild-sdks": { "Microsoft.Build.NoTargets": "3.7.0", "Microsoft.Build.Traversal": "3.4.0", - "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25060.4" + "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25076.1" } } diff --git a/src/SourceBuild/content/repo-projects/Directory.Build.props b/src/SourceBuild/content/repo-projects/Directory.Build.props index 6d200e0e2799..1570d17392c2 100644 --- a/src/SourceBuild/content/repo-projects/Directory.Build.props +++ b/src/SourceBuild/content/repo-projects/Directory.Build.props @@ -1,10 +1,12 @@ - + + $(MSBuildProjectName) - $(GitInfoDir)$(RepositoryName).props + + $([MSBuild]::NormalizePath('$(PrereqsDir)', 'git-info', '$(RepositoryName).props')) true false + @@ -62,6 +66,13 @@ false + + + $(OfficialBuildId.Split('.')[0]).$([MSBuild]::Add($(OfficialBuildId.Split('.')[1]), 100)) + + $([MSBuild]::NormalizePath('$(ProjectDirectory)', 'eng', 'common', 'build$(ShellExtension)')) @@ -72,7 +83,8 @@ $(BuildActions) $(FlagParameterPrefix)publish $(BuildActions) $(FlagParameterPrefix)sign - + $(FlagParameterPrefix)ci $(BuildArgs) $(FlagParameterPrefix)configuration $(Configuration) $(BuildArgs) -bl @@ -81,20 +93,25 @@ $(BuildArgs) /p:DotNetBuildOrchestrator=true + + $(BuildArgs) /p:TargetRid=$(TargetRid) + $(BuildArgs) /p:DotNetBuildPass=$(DotNetBuildPass) + $(BuildArgs) /p:CrossBuild=true - - $(BuildArgs) /p:DotNetBuildTests=true $(BuildArgs) /p:RestoreConfigFile=$(NuGetConfigFile) - $(BuildArgs) /p:DotNetBuildUseMonoRuntime=$(DotNetBuildUseMonoRuntime) + $(BuildArgs) /p:OfficialBuildId=$(OfficialBuildId) + $(BuildArgs) /p:ForceDryRunSigning=$(ForceDryRunSigning) + $(BuildArgs) /p:SourceBuiltAssetsDir=$(ArtifactsAssetsDir) $(BuildArgs) /p:SourceBuiltAssetManifestsDir=$(RepoAssetManifestsDir) - $(BuildArgs) /p:OfficialBuildId=$(OfficialBuildId) - $(BuildArgs) /p:ForceDryRunSigning=$(ForceDryRunSigning) + + + $(BuildArgs) /p:DefaultArtifactVisibility=Vertical @@ -108,11 +125,11 @@ $(FlagParameterPrefix)restore $(TestActions) $(FlagParameterPrefix)test - $(FlagParameterPrefix)ci + + $(FlagParameterPrefix)ci $(TestArgs) $(FlagParameterPrefix)configuration $(Configuration) $(TestArgs) /bl:artifacts/log/$(Configuration)/Test.binlog - - $(BuildScript) $(TestActions) $(TestArgs) @@ -138,8 +155,9 @@ - - + - - source - 30000001-1 - - - - - - - + - - - - - - - - - - - - - - - - - diff --git a/src/SourceBuild/content/repo-projects/Directory.Build.targets b/src/SourceBuild/content/repo-projects/Directory.Build.targets index c554a1082169..e901890fa803 100644 --- a/src/SourceBuild/content/repo-projects/Directory.Build.targets +++ b/src/SourceBuild/content/repo-projects/Directory.Build.targets @@ -9,6 +9,9 @@ + powershell -NoProfile "Get-PSDrive -PSProvider FileSystem -Name (Get-Item "$(RepoRoot.TrimEnd('\'))").PSDrive.Name" + df -h $(RepoRoot) + $(BuildArgs) $(FlagParameterPrefix)msbuildEngine dotnet @@ -34,11 +37,12 @@ $(BuildArgs) /p:PortableBuild=$(PortableBuild) $(BuildArgs) /p:RuntimeOS=$(RuntimeOS) $(BuildArgs) /p:BaseOS=$(BaseOS) + + + $(BuildArgs) /p:DotNetBuildTests=true - $(BuildScript) $(BuildActions) $(BuildArgs) - $(ArtifactsLogRepoDir)$(RepositoryName).log @@ -129,9 +133,8 @@ - + @@ -449,6 +452,20 @@ + + + + $(BuildArgs) /p:DotNetBuildTargetRidOnly=true + + $(BuildScript) $(BuildActions) $(BuildArgs) + + + + SetSourceBuiltSdkOverrides; + SetBuildProperties"> @@ -468,10 +486,8 @@ - - + + $(BuildCommand) @@ -602,6 +618,7 @@ DestinationFiles="$(NuGetPackageRoot)%(RecursiveDir)%(Filename)%(Extension)" SkipUnchangedFiles="true" Retries="5" + UseHardlinksIfPossible="true" Condition="'@(_InnerPackageCacheFiles)' != ''" /> @@ -625,9 +642,28 @@ Condition="'@(PrebuiltReportsToMove)' != ''" /> + + + + $([MSBuild]::NormalizeDirectory('$(BaseIntermediateOutputPath)', 'project-assets-json')) + + + + + + + + + @@ -646,35 +682,20 @@ IgnoreStandardErrorWarningFormat="true" IgnoreExitCode="true" /> + + + + - $([MSBuild]::NormalizeDirectory('$(ProjectDirectory)', 'artifacts', 'buildObj')) + rmdir "$(RepoArtifactsDir.TrimEnd('\'))" /s /q + rm -rf "$(RepoArtifactsDir)" - - - - - - + - - - - - - - - - - - - - - - + + @@ -720,7 +741,9 @@ - + @@ -734,6 +757,7 @@ + + $(BuildScript) $(TestActions) $(TestArgs) + + diff --git a/src/SourceBuild/content/repo-projects/aspnetcore.proj b/src/SourceBuild/content/repo-projects/aspnetcore.proj index 7108a2e27668..39d9c72c27b2 100644 --- a/src/SourceBuild/content/repo-projects/aspnetcore.proj +++ b/src/SourceBuild/content/repo-projects/aspnetcore.proj @@ -30,6 +30,9 @@ $(BuildArgs) /p:EnablePackageValidation=false true + + + true diff --git a/src/SourceBuild/content/repo-projects/efcore.proj b/src/SourceBuild/content/repo-projects/efcore.proj index 6813e941e370..b9b7451509db 100644 --- a/src/SourceBuild/content/repo-projects/efcore.proj +++ b/src/SourceBuild/content/repo-projects/efcore.proj @@ -1,5 +1,10 @@ + + + true + + diff --git a/src/SourceBuild/content/repo-projects/razor.proj b/src/SourceBuild/content/repo-projects/razor.proj index cdd00ec7c5b1..7d0576afa41d 100644 --- a/src/SourceBuild/content/repo-projects/razor.proj +++ b/src/SourceBuild/content/repo-projects/razor.proj @@ -1,13 +1,5 @@ - - - $(BuildArgs) /p:UsingToolMicrosoftNetCompilers=false - - $(BuildArgs) /p:TargetRid=$(TargetRid) - - diff --git a/src/SourceBuild/content/repo-projects/roslyn.proj b/src/SourceBuild/content/repo-projects/roslyn.proj index 36a0b85db7e3..5e157810df9b 100644 --- a/src/SourceBuild/content/repo-projects/roslyn.proj +++ b/src/SourceBuild/content/repo-projects/roslyn.proj @@ -3,6 +3,9 @@ true + + true + $(FlagParameterPrefix)restore $(BuildActions) $(FlagParameterPrefix)pack @@ -12,15 +15,16 @@ $(ProjectDirectory)build$(ShellExtension) - + + $(BuildArgs) $(FlagParameterPrefix)officialBuildId $(OfficialBuildId) $(BuildArgs) $(FlagParameterPrefix)officialSkipTests true $(BuildArgs) $(FlagParameterPrefix)officialSkipApplyOptimizationData true $(BuildArgs) $(FlagParameterPrefix)officialSourceBranchName placeholder $(BuildArgs) $(FlagParameterPrefix)officialVisualStudioDropAccessToken placeholder + - $(BuildArgs) /p:TargetRid=$(TargetRid) $(BuildArgs) /p:TreatWarningsAsErrors=false $(BuildArgs) /p:ApplyPartialNgenOptimization=false $(BuildArgs) /p:EnablePartialNgenOptimization=false diff --git a/src/SourceBuild/content/repo-projects/runtime.proj b/src/SourceBuild/content/repo-projects/runtime.proj index 5c187068e132..5c9771da6f8f 100644 --- a/src/SourceBuild/content/repo-projects/runtime.proj +++ b/src/SourceBuild/content/repo-projects/runtime.proj @@ -8,14 +8,28 @@ $(BuildArgs) $(FlagParameterPrefix)arch $(TargetArchitecture) $(BuildArgs) $(FlagParameterPrefix)os $(TargetOS) - $(BuildArgs) /p:TargetRid=$(TargetRid) + + true + true + true + + true + + true + + + $(BuildArgs) /p:DotNetBuildAllRuntimePacks=true + + $(BuildArgs) /p:DotNetBuildRuntimeWasmEnableThreads=true - $(BuildArgs) /p:DotNetBuildRuntimeNativeAOTRuntimePack=true $(BuildArgs) /p:DotNetBuildMonoEnableLLVM=$(DotNetBuildMonoEnableLLVM) $(BuildArgs) /p:DotNetBuildMonoAOTEnableLLVM=$(DotNetBuildMonoAOTEnableLLVM) $(BuildArgs) /p:DotNetBuildMonoBundleLLVMOptimizer=$(DotNetBuildMonoBundleLLVMOptimizer) - $(BuildArgs) /p:DotNetBuildMonoCrossAOT=$(DotNetBuildMonoCrossAOT) $(BuildArgs) $(FlagParameterPrefix)pgoinstrument + $(BuildArgs) /p:UseSystemLibs=$(UseSystemLibs) diff --git a/src/SourceBuild/content/repo-projects/scenario-tests.proj b/src/SourceBuild/content/repo-projects/scenario-tests.proj index ea2150209de3..2acd2f8bf0b7 100644 --- a/src/SourceBuild/content/repo-projects/scenario-tests.proj +++ b/src/SourceBuild/content/repo-projects/scenario-tests.proj @@ -4,10 +4,12 @@ false - $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'scenario-tests')) $([MSBuild]::NormalizeDirectory('$(ArtifactsTestResultsDir)', 'scenario-tests')) - $([MSBuild]::NormalizePath('$(SrcDir)', 'sdk', 'NuGet.config')) - $(ScenarioTestsArtifactsDir)NuGet.config + + $(TestArgs) /p:TestBinlogDir=$(ArtifactsLogRepoDir) + + $(TestArgs) /p:RestoreConfigFile=$(NuGetConfigFile) @@ -20,24 +22,18 @@ - - - + + + + <_CurrentDateTime>$([System.DateTime]::Now.ToString("yyyy-MM-dd_HH_mm_ss")) <_TestXmlOutputPath>$(ScenarioTestsResultsDir)$(_CurrentDateTime).xml - <_ScenarioTestsAdditionalArgs>--xml $(_TestXmlOutputPath) --target-rid $(TargetRid) --no-cleanup --no-traits Category=MultiTFM - - - <_TestRoot>$(ScenarioTestsArtifactsDir)artifacts/ + <_ScenarioTestsAdditionalArgs>--xml $(_TestXmlOutputPath) --target-rid $(TargetRid) --portable-rid $(PortableRid) --no-cleanup --no-traits Category=MultiTFM @@ -48,12 +44,13 @@ + + diff --git a/src/SourceBuild/content/repo-projects/sdk.proj b/src/SourceBuild/content/repo-projects/sdk.proj index 7f34a2f370f9..d374626251e9 100644 --- a/src/SourceBuild/content/repo-projects/sdk.proj +++ b/src/SourceBuild/content/repo-projects/sdk.proj @@ -1,4 +1,4 @@ - + true @@ -6,7 +6,6 @@ $(BuildArgs) -nativeToolsOnMachine $(BuildArgs) /p:PackageProjectUrl=https://github.com/dotnet/sdk $(BuildArgs) /p:PortableRid=$(PortableRid) - $(BuildArgs) /p:TargetRid=$(TargetRid) $(BuildArgs) $(FlagParameterPrefix)v $(LogVerbosity) @@ -32,7 +31,7 @@ $(BuildArgs) /p:BuildSdkDeb=true /p:BuildSdkRpm=true - $(BuildArgs) /p:SkipBuildingInstallers=true /p:SkipBuildingSdkBundle=true + $(BuildArgs) /p:SkipBuildingInstallers=true /p:SkipBuildingSdkBundle=true $(BuildArgs) /p:PublicBaseURL=file:%2F%2F$(ArtifactsAssetsDir) @@ -90,4 +89,21 @@ + + + + + + + + + + + + + + + + + diff --git a/src/SourceBuild/content/repo-projects/vstest.proj b/src/SourceBuild/content/repo-projects/vstest.proj index 77f902ee2189..1ceba61e8c63 100644 --- a/src/SourceBuild/content/repo-projects/vstest.proj +++ b/src/SourceBuild/content/repo-projects/vstest.proj @@ -2,6 +2,9 @@ true + + + true diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/BasicScenarioTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/BasicScenarioTests.cs index f9fe8acd36df..336316f2fa50 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/BasicScenarioTests.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/BasicScenarioTests.cs @@ -19,7 +19,7 @@ public class BasicScenarioTests : SdkTests { public BasicScenarioTests(ITestOutputHelper outputHelper) : base(outputHelper) { } - // [Theory(Skip="https://github.com/dotnet/sdk/issues/42920")] + [Theory] [MemberData(nameof(GetScenarioObjects))] public void VerifyScenario(TestScenario scenario) => scenario.Execute(DotNetHelper); diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/DotNetFormatTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/DotNetFormatTests.cs index 0de57851de53..b3c7e05e1650 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/DotNetFormatTests.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/DotNetFormatTests.cs @@ -20,7 +20,7 @@ public DotNetFormatTests(ITestOutputHelper outputHelper) : base(outputHelper) { /// /// Format an unformatted project and verify that the output matches the pre-computed solution. /// - // [Fact(Skip="https://github.com/dotnet/sdk/issues/42920")] + [Fact] public void FormatProject() { if (DotNetHelper.IsMonoRuntime) diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/DotNetWatchTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/DotNetWatchTests.cs index e39c47507343..60f81c464add 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/DotNetWatchTests.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/DotNetWatchTests.cs @@ -13,7 +13,7 @@ public class DotNetWatchTests : SdkTests { public DotNetWatchTests(ITestOutputHelper outputHelper) : base(outputHelper) { } - // [Fact(Skip="https://github.com/dotnet/sdk/issues/42920")] + [Fact] public void WatchTests() { if (DotNetHelper.IsMonoRuntime) @@ -36,7 +36,7 @@ public void WatchTests() void processConfigCallback(Process process) { - const string waitingString = "Waiting for changes"; + const string waitingString = "Waiting for a file to change"; const string expectedString = "Hello from dotnet watch!"; bool fileChanged = false; diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/LicenseScanTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/LicenseScanTests.cs index f41c98be5861..b4010ccdade8 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/LicenseScanTests.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/LicenseScanTests.cs @@ -56,6 +56,7 @@ public class LicenseScanTests : TestBase "bsd-original", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/bsd-original.LICENSE "bsd-original-uc", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/bsd-original-uc.LICENSE "bsd-simplified", // https://opensource.org/license/bsd-2-clause/ + "bsd-zero", // https://opensource.org/license/0bsd/ "bytemark", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/bytemark.LICENSE "bzip2-libbzip-2010", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/bzip2-libbzip-2010.LICENSE "cc0-1.0", // https://creativecommons.org/publicdomain/zero/1.0/legalcode @@ -70,6 +71,7 @@ public class LicenseScanTests : TestBase "generic-cla", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/generic-cla.LICENSE "gpl-1.0-plus", // https://opensource.org/license/gpl-1-0/ "gpl-2.0", // https://opensource.org/license/gpl-2-0/ + "gpl-3.0", // https://opensource.org/license/gpl-3-0/ "ietf", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/ietf.LICENSE "gpl-2.0-plus WITH autoconf-simple-exception-2.0", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/rules/gpl-2.0-plus_with_autoconf-simple-exception-2.0_8.RULE "gpl-2.0 WITH gcc-linking-exception-2.0", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/rules/gpl-2.0_with_gcc-linking-exception-2.0_6.RULE @@ -102,6 +104,7 @@ public class LicenseScanTests : TestBase "sax-pd", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/sax-pd.LICENSE "unicode", // https://opensource.org/license/unicode-inc-license-agreement-data-files-and-software/ "unicode-mappings", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/unicode-mappings.LICENSE + "unlicense", // https://opensource.org/license/unlicense/ "uoi-ncsa", // https://opensource.org/license/uoi-ncsa-php/ "w3c-software-19980720", // https://opensource.org/license/w3c/ "w3c-software-doc-20150513", // https://opensource.org/license/w3c/ diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/OmniSharpTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/OmniSharpTests.cs index 9d684663d273..4e53ada8cfff 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/OmniSharpTests.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/OmniSharpTests.cs @@ -20,7 +20,7 @@ namespace Microsoft.DotNet.SourceBuild.Tests; public class OmniSharpTests : SdkTests { // Update version as new releases become available: https://github.com/OmniSharp/omnisharp-roslyn/releases - private const string OmniSharpReleaseVersion = "1.39.12"; + private const string OmniSharpReleaseVersion = "1.39.13"; private string OmniSharpDirectory { get; } = Path.Combine(Directory.GetCurrentDirectory(), nameof(OmniSharpTests)); diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/SymbolsTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/SymbolsTests.cs index 75ffc708f345..912fa9b376f6 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/SymbolsTests.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/SymbolsTests.cs @@ -24,7 +24,7 @@ public SymbolsTests(ITestOutputHelper outputHelper) : base(outputHelper) { } /// /// Verifies that all symbols have valid sourcelinks. /// - // [Fact(Skip="https://github.com/dotnet/sdk/issues/42920")] + [Fact] public void VerifySdkSymbols() { try @@ -66,6 +66,10 @@ private IList VerifySdkFilesHaveMatchingSymbols(string symbolsRoot, stri { Assert.True(Directory.Exists(sdkRoot), $"Path, with SDK files to validate, does not exist: {sdkRoot}"); + // Normalize paths, to ensure proper string replacement + symbolsRoot = symbolsRoot.TrimEnd(Path.DirectorySeparatorChar); + sdkRoot = sdkRoot.TrimEnd(Path.DirectorySeparatorChar); + var failedFiles = new ConcurrentBag(); IEnumerable allFiles = Directory.GetFiles(sdkRoot, "*", SearchOption.AllDirectories); diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/WebScenarioTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/WebScenarioTests.cs index 6f3cd28f5233..b2ce04a620cb 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/WebScenarioTests.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/WebScenarioTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -20,7 +21,7 @@ public class WebScenarioTests : SdkTests { public WebScenarioTests(ITestOutputHelper outputHelper) : base(outputHelper) { } - // [Theory(Skip="https://github.com/dotnet/sdk/issues/42920")] + [Theory] [MemberData(nameof(GetScenarioObjects))] public void VerifyScenario(TestScenario scenario) => scenario.Execute(DotNetHelper); @@ -37,8 +38,7 @@ private static IEnumerable GetScenarios() yield return new(nameof(WebScenarioTests), DotNetLanguage.CSharp, DotNetTemplate.Razor, DotNetActions.Build | DotNetActions.Run | DotNetActions.Publish); yield return new(nameof(WebScenarioTests), DotNetLanguage.CSharp, DotNetTemplate.BlazorWasm, DotNetActions.Build | DotNetActions.Run | DotNetActions.Publish); - // Disabled due to .NET 10.0 transition. See https://github.com/dotnet/sdk/pull/42969 - // yield return new(nameof(WebScenarioTests), DotNetLanguage.CSharp, DotNetTemplate.WebApp, DotNetActions.PublishSelfContained, VerifyRuntimePacksForSelfContained); + yield return new(nameof(WebScenarioTests), DotNetLanguage.CSharp, DotNetTemplate.WebApp, DotNetActions.PublishSelfContained, VerifyRuntimePacksForSelfContained); yield return new(nameof(WebScenarioTests), DotNetLanguage.CSharp, DotNetTemplate.Worker); } @@ -50,9 +50,30 @@ private static void VerifyRuntimePacksForSelfContained(string projectPath) string projNugetCachePath = Path.Combine(projectPath, "obj", "project.nuget.cache"); JsonNode? projNugetCache = JsonNode.Parse(File.ReadAllText(projNugetCachePath)); - string? restoredPackageFiles = projNugetCache?["expectedPackageFiles"]?.ToString(); + JsonArray? restoredPackageFiles = (JsonArray?)projNugetCache?["expectedPackageFiles"]; Assert.True(restoredPackageFiles is not null, "Failed to parse project.nuget.cache"); - Assert.True("[]" == restoredPackageFiles, "Runtime packs were retrieved from NuGet instead of the SDK"); + + string[] allowedPackages = [ + // Temporarily allowed due to https://github.com/dotnet/sdk/issues/46165 + // TODO: Remove this once the issue is resolved + "Microsoft.AspNetCore.App.Internal.Assets" + ]; + + string packagesDirectory = Path.Combine(Environment.CurrentDirectory, "packages"); + + IEnumerable packages = restoredPackageFiles + .Select(file => + { + string path = file.ToString(); + path = path.Substring(packagesDirectory.Length + 1); // trim the leading path up to the package name directory + return path.Substring(0, path.IndexOf('/')); // trim the rest of the path + }) + .Except(allowedPackages, StringComparer.OrdinalIgnoreCase); + + if (packages.Any()) + { + Assert.Fail($"The following runtime packs were retrieved from NuGet instead of the SDK: {string.Join(",", packages.ToArray())}"); + } } } diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/assets/LicenseScanTests/LicenseExclusions.txt b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/assets/LicenseScanTests/LicenseExclusions.txt index c2c145f1963b..c4f0b1358ec2 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/assets/LicenseScanTests/LicenseExclusions.txt +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.Tests/assets/LicenseScanTests/LicenseExclusions.txt @@ -68,7 +68,9 @@ src/diagnostics/THIRD-PARTY-NOTICES.TXT|codesourcery-2004 # False positive src/efcore/test/EfCore.Tests/ChangeTracking/ComplexPropertyEntryTest.cs|proprietary-license +src/efcore/test/EFCore.Tests/ChangeTracking/EntityEntryTest.cs|proprietary-license src/efcore/test/EfCore.Tests/ChangeTracking/MemberEntryTest.cs|proprietary-license +src/efcore/test/EFCore.Tests/ChangeTracking/PropertyEntryTest.cs|proprietary-license # # fsharp @@ -76,6 +78,7 @@ src/efcore/test/EfCore.Tests/ChangeTracking/MemberEntryTest.cs|proprietary-licen # Applies to installer, not source src/fsharp/setup/resources/eula/*.rtf +src/fsharp/tests/fsharp/core/members/ops/THIRD-PARTY-NOTICES.TXT|unknown-license-reference # # msbuild @@ -108,6 +111,7 @@ src/nuget-client/test/NuGet.Core.Tests/NuGet.Packaging.Test/DefaultManifestValue src/nuget-client/test/NuGet.Core.Tests/NuGet.Packaging.Test/LicensesTests/LicenseExpressionTokenizerTests.cs src/nuget-client/test/NuGet.Core.Tests/NuGet.Packaging.Test/LicensesTests/NuGetLicenseExpressionParserTests.cs src/nuget-client/test/NuGet.Core.Tests/NuGet.Packaging.Test/LicensesTests/NuGetLicenseTests.cs +src/nuget-client/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs|389-exception src/nuget-client/test/TestUtilities/Test.Utility/JsonData.cs # @@ -186,6 +190,9 @@ src/source-build-externals/src/xunit/README.md|free-unknown src/source-build-externals/src/xunit/src/xunit.assert/Asserts/README.md|free-unknown src/source-build-externals/src/xunit/tools/builder/common/README.md|free-unknown +# Configuration, doesn't apply to source directly +src/source-build-externals/src/vs-solutionpersistence/stylecop.json + # Scanner is identifying the https://github.com/SixLabors/ImageSharp/blob/master/LICENSE license as unknown. But this license is not applicable because we're # relying on the Spectre.Console distribution. # See https://github.com/dotnet/dotnet/blob/c6a7278fbb7d79fa3d1f386ef0dc8474043ed06c/src/source-build-externals/src/spectre-console/README.md?plain=1#L104 @@ -238,7 +245,7 @@ src/wpf/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/FontE src/wpf/eng/WpfArcadeSdk/tools/AvTrace/GenTraceSources.pl|proprietary-license src/wpf/eng/WpfArcadeSdk/tools/GenXmlStringTable.pl|proprietary-license -# False positive - https://github.com/dotnet/source-build/issues/4373 +# False positive src/wpf/src/Microsoft.DotNet.Wpf/src/PresentationUI/MS/Internal/Documents/RMPublishingDialog.RightsTable.cs|unknown-license-reference src/wpf/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/WindowBackdropType.cs|bsd-2-clause-views src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Resources/*.xaml|bsd-2-clause-views @@ -246,3 +253,7 @@ src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Resourc src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Styles/*.xaml|bsd-2-clause-views src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Styles/*.xaml|mpl-2.0 src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Themes/*.xaml|bsd-2-clause-views +src/wpf/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/CompoundFile/RightsManagementEncryptionTransform.cs|proprietary-license + +# Test data +src/wpf/src/Microsoft.DotNet.Wpf/tests/UnitTests/WindowsBase.Tests/System/Security/RightsManagement/PublishLicenseTests.cs|unknown-license-reference diff --git a/src/SourceBuild/content/test/tests.proj b/src/SourceBuild/content/test/tests.proj index f7bda2620e07..234d741ad3db 100644 --- a/src/SourceBuild/content/test/tests.proj +++ b/src/SourceBuild/content/test/tests.proj @@ -13,8 +13,11 @@ cross-build of using Mariner to build for Alpine (linux vs linux-musl). --> <_RunScenarioTests Condition="'$(BuildOS)' != 'windows' and '$(DotNetBuildSourceOnly)' != 'true' and '$(__PortableTargetOS.ToLowerInvariant())' != '$(TargetOS.ToLowerInvariant())'">false - - <_RunScenarioTests Condition="'$(UseOfficialBuildVersioning)' == 'false'">false + + <_RunScenarioTests Condition="'$(ShortStack)' == 'true' or '$(PgoInstrument)' == 'true'">false + + + <_RunScenarioTests Condition="'$(DotNetBuildPass)' != '' and '$(DotNetBuildPass)' != '1'">false @@ -24,14 +27,17 @@ - + + - + diff --git a/src/SourceBuild/patches/nuget-client/0001-use-the-documented-artifact-ext.patch b/src/SourceBuild/patches/nuget-client/0001-use-the-documented-artifact-ext.patch new file mode 100644 index 000000000000..39081266220a --- /dev/null +++ b/src/SourceBuild/patches/nuget-client/0001-use-the-documented-artifact-ext.patch @@ -0,0 +1,61 @@ +From 62c4b5f114850d39efdca3df3b9ee83cc0f424ff Mon Sep 17 00:00:00 2001 +From: Jeremy Koritzinsky +Date: Tue, 21 Jan 2025 16:16:49 -0800 +Subject: [PATCH 1/2] Use the documented Artifact extension point to add + artifacts + +The Artifact extension point handles symbol packages automatically for source-build, and it automatically gets support for new features like Artifact Visibility (required for https://github.com/dotnet/sdk/pull/46063) +Backport: https://github.com/NuGet/NuGet.Client/pull/6233 +--- + eng/Publishing.props | 11 +++-------- + 1 file changed, 3 insertions(+), 8 deletions(-) + +diff --git a/eng/Publishing.props b/eng/Publishing.props +index 38810c73428..1175200dd59 100644 +--- a/eng/Publishing.props ++++ b/eng/Publishing.props +@@ -1,11 +1,6 @@ + +- + +- +- <_SymbolsPackages Include="$(ArtifactsDir)nupkgs/*.symbols.nupkg" /> +- ++ + +- +- +\ No newline at end of file ++ + +From 9072cb03cb5c2958df318f59389547caa5de2c8a Mon Sep 17 00:00:00 2001 +From: Jeremy Koritzinsky +Date: Wed, 22 Jan 2025 10:07:47 -0800 +Subject: [PATCH 2/2] Formatting and PR feedback + +--- + eng/Publishing.props | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/eng/Publishing.props b/eng/Publishing.props +index 1175200dd59..41f498d4d4a 100644 +--- a/eng/Publishing.props ++++ b/eng/Publishing.props +@@ -1,6 +1,8 @@ +- +- +- +- +- ++ ++ ++ ++ ++ ++ ++ diff --git a/src/SourceBuild/patches/razor/0001-Remove-unused-fields.patch b/src/SourceBuild/patches/razor/0001-Remove-unused-fields.patch deleted file mode 100644 index e710243f76d6..000000000000 --- a/src/SourceBuild/patches/razor/0001-Remove-unused-fields.patch +++ /dev/null @@ -1,45 +0,0 @@ -From faa695199c8b8886c0d923f25a57c9728afeafbf Mon Sep 17 00:00:00 2001 -From: Matt Thalman -Date: Tue, 7 Jan 2025 14:48:06 -0600 -Subject: [PATCH] Remove unused fields - -Backport: https://github.com/dotnet/razor/pull/11358 ---- - .../Microsoft.AspNetCore.Razor.LanguageServer/LspServices.cs | 4 +--- - .../AutoInsert/RemoteAutoInsertService.cs | 1 - - 2 files changed, 1 insertion(+), 4 deletions(-) - -diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspServices.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspServices.cs -index 43a17a0402..01bf4ada70 100644 ---- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspServices.cs -+++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspServices.cs -@@ -14,16 +14,14 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer; - internal class LspServices : ILspServices - { - private readonly IServiceProvider _serviceProvider; -- private readonly IEnumerable _startupServices; - public bool IsDisposed = false; - - public LspServices(IServiceCollection serviceCollection) - { - serviceCollection.AddSingleton(this); - _serviceProvider = serviceCollection.BuildServiceProvider(); -- - // Create all startup services -- _startupServices = _serviceProvider.GetServices(); -+ _serviceProvider.GetServices(); - } - - public ImmutableArray GetRegisteredServices() -diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/AutoInsert/RemoteAutoInsertService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/AutoInsert/RemoteAutoInsertService.cs -index 27dcc78952..f8ab749b66 100644 ---- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/AutoInsert/RemoteAutoInsertService.cs -+++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/AutoInsert/RemoteAutoInsertService.cs -@@ -32,7 +32,6 @@ internal sealed class RemoteAutoInsertService(in ServiceArgs args) - } - - private readonly IAutoInsertService _autoInsertService = args.ExportProvider.GetExportedValue(); -- private readonly IFilePathService _filePathService = args.ExportProvider.GetExportedValue(); - private readonly IRazorFormattingService _razorFormattingService = args.ExportProvider.GetExportedValue(); - - protected override IDocumentPositionInfoStrategy DocumentPositionInfoStrategy => PreferHtmlInAttributeValuesDocumentPositionInfoStrategy.Instance; diff --git a/src/SourceBuild/patches/razor/0002-Remove-unused-field-in-RazorContentTypeChangeListener.patch b/src/SourceBuild/patches/razor/0002-Remove-unused-field-in-RazorContentTypeChangeListener.patch deleted file mode 100644 index 8c7dcd117401..000000000000 --- a/src/SourceBuild/patches/razor/0002-Remove-unused-field-in-RazorContentTypeChangeListener.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 1d6f0ce17c97fcf541b5f45b000b4f54356e8f25 Mon Sep 17 00:00:00 2001 -From: Matt Thalman -Date: Tue, 7 Jan 2025 18:28:41 -0600 -Subject: [PATCH] Remove unused field in RazorContentTypeChangeListener - -Backport: https://github.com/dotnet/razor/pull/11361 ---- - .../LanguageClient/RazorContentTypeChangeListener.cs | 8 -------- - .../LanguageClient/RazorContentTypeChangeListenerTest.cs | 1 - - 2 files changed, 9 deletions(-) - -diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/RazorContentTypeChangeListener.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/RazorContentTypeChangeListener.cs -index dcc90c5787..13fb4b0696 100644 ---- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/RazorContentTypeChangeListener.cs -+++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/RazorContentTypeChangeListener.cs -@@ -18,7 +18,6 @@ internal class RazorContentTypeChangeListener : ITextBufferContentTypeListener - private readonly TrackingLSPDocumentManager _lspDocumentManager; - private readonly ITextDocumentFactoryService _textDocumentFactory; - private readonly ILspEditorFeatureDetector _lspEditorFeatureDetector; -- private readonly IEditorOptionsFactoryService _editorOptionsFactory; - private readonly IFileToContentTypeService _fileToContentTypeService; - - [ImportingConstructor] -@@ -26,7 +25,6 @@ internal class RazorContentTypeChangeListener : ITextBufferContentTypeListener - ITextDocumentFactoryService textDocumentFactory, - LSPDocumentManager lspDocumentManager, - ILspEditorFeatureDetector lspEditorFeatureDetector, -- IEditorOptionsFactoryService editorOptionsFactory, - IFileToContentTypeService fileToContentTypeService) - { - if (textDocumentFactory is null) -@@ -44,11 +42,6 @@ internal class RazorContentTypeChangeListener : ITextBufferContentTypeListener - throw new ArgumentNullException(nameof(lspEditorFeatureDetector)); - } - -- if (editorOptionsFactory is null) -- { -- throw new ArgumentNullException(nameof(editorOptionsFactory)); -- } -- - if (fileToContentTypeService is null) - { - throw new ArgumentNullException(nameof(fileToContentTypeService)); -@@ -63,7 +56,6 @@ internal class RazorContentTypeChangeListener : ITextBufferContentTypeListener - - _textDocumentFactory = textDocumentFactory; - _lspEditorFeatureDetector = lspEditorFeatureDetector; -- _editorOptionsFactory = editorOptionsFactory; - _fileToContentTypeService = fileToContentTypeService; - } - -diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LanguageClient/RazorContentTypeChangeListenerTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LanguageClient/RazorContentTypeChangeListenerTest.cs -index d01ea46d5c..d6afae6491 100644 ---- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LanguageClient/RazorContentTypeChangeListenerTest.cs -+++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LanguageClient/RazorContentTypeChangeListenerTest.cs -@@ -226,7 +226,6 @@ public class RazorContentTypeChangeListenerTest : ToolingTestBase - textDocumentFactory, - lspDocumentManager, - lspEditorFeatureDetector, -- Mock.Of(s => s.GetOptions(It.IsAny()) == Mock.Of(MockBehavior.Strict), MockBehavior.Strict), - fileToContentTypeService); - - return listener; diff --git a/src/SourceBuild/patches/razor/0003-Remove-unnecessary-using.patch b/src/SourceBuild/patches/razor/0003-Remove-unnecessary-using.patch deleted file mode 100644 index 2ad84ab1351c..000000000000 --- a/src/SourceBuild/patches/razor/0003-Remove-unnecessary-using.patch +++ /dev/null @@ -1,23 +0,0 @@ -From fa8b9938dfaa72c790a1bf4a657af77ef2de5f13 Mon Sep 17 00:00:00 2001 -From: David Wengier -Date: Wed, 8 Jan 2025 12:03:12 +1100 -Subject: [PATCH] Remove using - -Backport: https://github.com/dotnet/razor/pull/11361 - ---- - .../LanguageClient/RazorContentTypeChangeListener.cs | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/RazorContentTypeChangeListener.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/RazorContentTypeChangeListener.cs -index 13fb4b0696..535223227b 100644 ---- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/RazorContentTypeChangeListener.cs -+++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/RazorContentTypeChangeListener.cs -@@ -5,7 +5,6 @@ using System; - using System.ComponentModel.Composition; - using Microsoft.VisualStudio.LanguageServer.ContainedLanguage; - using Microsoft.VisualStudio.Text; --using Microsoft.VisualStudio.Text.Editor; - using Microsoft.VisualStudio.Utilities; - - namespace Microsoft.VisualStudio.Razor.LanguageClient; diff --git a/src/SourceBuild/patches/roslyn/0001-Use-BaseOS-instead-of-TargetRid-when-its-available.patch b/src/SourceBuild/patches/roslyn/0001-Use-BaseOS-instead-of-TargetRid-when-its-available.patch new file mode 100644 index 000000000000..cf2d19f1ce75 --- /dev/null +++ b/src/SourceBuild/patches/roslyn/0001-Use-BaseOS-instead-of-TargetRid-when-its-available.patch @@ -0,0 +1,34 @@ +From fe7b6d17a00a69b6bb8cb25d640af56f74a60032 Mon Sep 17 00:00:00 2001 +From: Jeremy Koritzinsky +Date: Tue, 21 Jan 2025 11:31:58 -0800 +Subject: [PATCH] Use BaseOS instead of TargetRid when its available. + +In Source Build, BaseOS is the portable runtime identifier for TargetRid. + +Backport: https://github.com/dotnet/roslyn/pull/76838 + +--- + .../Microsoft.CodeAnalysis.LanguageServer.csproj | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +index 9b556fcdb8f..a76305b4a29 100644 +--- a/src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj ++++ b/src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +@@ -45,12 +45,13 @@ + $(ArtifactsDir)/LanguageServer/$(Configuration)/$(TargetFramework)/neutral + + +- + $(TargetRid) +- win-x64;win-arm64;linux-x64;linux-arm64;linux-musl-x64;linux-musl-arm64;osx-x64;osx-arm64 ++ $(BaseOS) ++ win-x64;win-arm64;linux-x64;linux-arm64;linux-musl-x64;linux-musl-arm64;osx-x64;osx-arm64 + + true + diff --git a/src/SourceBuild/patches/winforms/0001-React-to-compiler-analyzer-warning-error.patch b/src/SourceBuild/patches/winforms/0001-React-to-compiler-analyzer-warning-error.patch new file mode 100644 index 000000000000..0874a9b44e68 --- /dev/null +++ b/src/SourceBuild/patches/winforms/0001-React-to-compiler-analyzer-warning-error.patch @@ -0,0 +1,24 @@ +From 65300cd19e498c2d525be2bc406b3792350bb670 Mon Sep 17 00:00:00 2001 +From: Viktor Hofer +Date: Fri, 24 Jan 2025 13:14:11 +0100 +Subject: [PATCH] React to compiler analyzer warning/error + +Backport: https://github.com/dotnet/winforms/pull/12837 + +--- + .../Private/Windows/Core/Nrbf/SerializationRecordExtensions.cs | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/System.Private.Windows.Core/src/System/Private/Windows/Nrbf/SerializationRecordExtensions.cs b/src/System.Private.Windows.Core/src/System/Private/Windows/Nrbf/SerializationRecordExtensions.cs +index 7f9ba95a7..6537c9da0 100644 +--- a/src/System.Private.Windows.Core/src/System/Private/Windows/Nrbf/SerializationRecordExtensions.cs ++++ b/src/System.Private.Windows.Core/src/System/Private/Windows/Nrbf/SerializationRecordExtensions.cs +@@ -349,7 +349,7 @@ internal static class SerializationRecordExtensions + || !classInfo.HasMember("_size") + || classInfo.GetRawValue("_size") is not int size + || !classInfo.TypeName.IsConstructedGenericType +- || classInfo.TypeName.GetGenericTypeDefinition().Name != typeof(List<>).Name ++ || classInfo.TypeName.GetGenericTypeDefinition().Name != nameof(List<>) + || classInfo.TypeName.GetGenericArguments().Length != 1 + || classInfo.GetRawValue("_items") is not ArrayRecord arrayRecord + || !IsPrimitiveArrayRecord(arrayRecord)) diff --git a/src/StaticWebAssetsSdk/Tasks/ScopedCss/ConcatenateCssFiles.cs b/src/StaticWebAssetsSdk/Tasks/ScopedCss/ConcatenateCssFiles.cs index 682b6fb7aaed..4c37f65dcdca 100644 --- a/src/StaticWebAssetsSdk/Tasks/ScopedCss/ConcatenateCssFiles.cs +++ b/src/StaticWebAssetsSdk/Tasks/ScopedCss/ConcatenateCssFiles.cs @@ -6,7 +6,6 @@ #if NET9_0_OR_GREATER using System.Globalization; #endif -using System.Security.Cryptography; using Microsoft.Build.Framework; namespace Microsoft.AspNetCore.StaticWebAssets.Tasks; @@ -106,31 +105,7 @@ public override bool Execute() private static bool SameContent(string content, string outputFilePath) { - var contentHash = GetContentHash(content); - var outputContent = File.ReadAllText(outputFilePath); - var outputContentHash = GetContentHash(outputContent); - - for (var i = 0; i < outputContentHash.Length; i++) - { - if (outputContentHash[i] != contentHash[i]) - { - return false; - } - } - - return true; - - static byte[] GetContentHash(string content) - { - var data = Encoding.UTF8.GetBytes(content); -#if !NET9_0_OR_GREATER - using var sha256 = SHA256.Create(); - var result = sha256.ComputeHash(data); -#else - var result = SHA256.HashData(data); -#endif - return result; - } + return string.Equals(content, outputContent); } } diff --git a/src/StaticWebAssetsSdk/Tasks/ScopedCss/ConcatenateCssFiles50.cs b/src/StaticWebAssetsSdk/Tasks/ScopedCss/ConcatenateCssFiles50.cs index 7e1cc9ee3e45..3e458d9d2471 100644 --- a/src/StaticWebAssetsSdk/Tasks/ScopedCss/ConcatenateCssFiles50.cs +++ b/src/StaticWebAssetsSdk/Tasks/ScopedCss/ConcatenateCssFiles50.cs @@ -6,7 +6,6 @@ #if NET9_0_OR_GREATER using System.Globalization; #endif -using System.Security.Cryptography; using Microsoft.Build.Framework; namespace Microsoft.AspNetCore.StaticWebAssets.Tasks; @@ -109,29 +108,7 @@ public override bool Execute() private static bool SameContent(string content, string outputFilePath) { - var contentHash = GetContentHash(content); - var outputContent = File.ReadAllText(outputFilePath); - var outputContentHash = GetContentHash(outputContent); - - for (var i = 0; i < outputContentHash.Length; i++) - { - if (outputContentHash[i] != contentHash[i]) - { - return false; - } - } - - return true; - - static byte[] GetContentHash(string content) - { -#if NET472_OR_GREATER - using var sha256 = SHA256.Create(); - return sha256.ComputeHash(Encoding.UTF8.GetBytes(content)); -#else - return SHA256.HashData(Encoding.UTF8.GetBytes(content)); -#endif - } + return string.Equals(content, outputContent); } } diff --git a/src/Tasks/Common/Resources/Strings.resx b/src/Tasks/Common/Resources/Strings.resx index 527418c3a435..995f14ea93d5 100644 --- a/src/Tasks/Common/Resources/Strings.resx +++ b/src/Tasks/Common/Resources/Strings.resx @@ -957,10 +957,7 @@ You may need to build the project on another operating system or architecture, o NETSDK1218: This project has a transitive dependency on the full Windows SDK projections (including Windows.UI.Xaml.* types), but does not specify the UseUwp property. That must be enabled to ensure that .NET types are projected and marshalled correctly for interop scenarios with these XAML types. {StrBegins="NETSDK1218: "} - - NETSDK1219: UseUwp and all associated functionality are currently experimental and not officially supported. - {StrBegins="NETSDK1219: "} - + NETSDK1220: UseUwp and all associated functionality require using a TFM of 'net8.0-windows' or greater. {StrBegins="NETSDK1220: "} diff --git a/src/Tasks/Common/Resources/xlf/Strings.cs.xlf b/src/Tasks/Common/Resources/xlf/Strings.cs.xlf index dab129a08c52..b54862b41a69 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.cs.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.cs.xlf @@ -1033,11 +1033,6 @@ The following are names of parameters or literal values and should not be transl NETSDK1057: Používáte verzi Preview rozhraní .NET. Viz: https://aka.ms/dotnet-support-policy {StrBegins="NETSDK1057: "} - - NETSDK1219: UseUwp and all associated functionality are currently experimental and not officially supported. - NETSDK1219: UseUwp a všechny související funkce jsou v současné době experimentální a nejsou oficiálně podporovány. - {StrBegins="NETSDK1219: "} - NETSDK1131: Producing a managed Windows Metadata component with WinMDExp is not supported when targeting {0}. NETSDK1131: Vytvoření spravované komponenty Metadata Windows s WinMDExp se při cílení na {0} nepodporuje. diff --git a/src/Tasks/Common/Resources/xlf/Strings.de.xlf b/src/Tasks/Common/Resources/xlf/Strings.de.xlf index 9e39c2d5bd3e..93de43041e8f 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.de.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.de.xlf @@ -1033,11 +1033,6 @@ The following are names of parameters or literal values and should not be transl NETSDK1057: Sie verwenden eine Vorschauversion von .NET. Weitere Informationen: https://aka.ms/dotnet-support-policy {StrBegins="NETSDK1057: "} - - NETSDK1219: UseUwp and all associated functionality are currently experimental and not officially supported. - NETSDK1219: UseUwp und alle zugehörigen Funktionen sind derzeit experimentell und werden nicht offiziell unterstützt. - {StrBegins="NETSDK1219: "} - NETSDK1131: Producing a managed Windows Metadata component with WinMDExp is not supported when targeting {0}. NETSDK1131: Das Erstellen einer verwalteten Windows-Metadatenkomponente mit WinMDExp wird mit dem Ziel "{0}" nicht unterstützt. diff --git a/src/Tasks/Common/Resources/xlf/Strings.es.xlf b/src/Tasks/Common/Resources/xlf/Strings.es.xlf index ea92a565fb71..76822ef6d9f2 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.es.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.es.xlf @@ -1033,11 +1033,6 @@ The following are names of parameters or literal values and should not be transl NETSDK1057: Está usando una versión preliminar de .NET. Visite: https://aka.ms/dotnet-support-policy {StrBegins="NETSDK1057: "} - - NETSDK1219: UseUwp and all associated functionality are currently experimental and not officially supported. - NETSDK1219: UseUwp y toda la funcionalidad asociada son experimentales actualmente y no se admiten oficialmente. - {StrBegins="NETSDK1219: "} - NETSDK1131: Producing a managed Windows Metadata component with WinMDExp is not supported when targeting {0}. NETSDK1131: No se admite la generación de un componente administrado de metadatos de Windows con WinMDExp cuando el destino es {0}. diff --git a/src/Tasks/Common/Resources/xlf/Strings.fr.xlf b/src/Tasks/Common/Resources/xlf/Strings.fr.xlf index 2ad426ab793a..7036da8215f4 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.fr.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.fr.xlf @@ -1033,11 +1033,6 @@ The following are names of parameters or literal values and should not be transl NETSDK1057: vous utilisez une version d'aperçu de .NET. Voir : https://aka.ms/dotnet-support-policy {StrBegins="NETSDK1057: "} - - NETSDK1219: UseUwp and all associated functionality are currently experimental and not officially supported. - NETSDK1219: UseUwp et toutes les fonctionnalités associées sont actuellement expérimentales et ne sont pas officiellement prises en charge. - {StrBegins="NETSDK1219: "} - NETSDK1131: Producing a managed Windows Metadata component with WinMDExp is not supported when targeting {0}. NETSDK1131: la production d'un composant de métadonnées Windows managé avec WinMDExp n'est pas prise en charge pour le ciblage de {0}. diff --git a/src/Tasks/Common/Resources/xlf/Strings.it.xlf b/src/Tasks/Common/Resources/xlf/Strings.it.xlf index 1319141e2c98..c8a8c654d286 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.it.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.it.xlf @@ -1033,11 +1033,6 @@ The following are names of parameters or literal values and should not be transl NETSDK1057: si sta usando una versione in anteprima di .NET. Vedere https://aka.ms/dotnet-support-policy {StrBegins="NETSDK1057: "} - - NETSDK1219: UseUwp and all associated functionality are currently experimental and not officially supported. - NETSDK1219: UseUwp e tutte le funzionalità associate sono attualmente sperimentali e non sono ufficialmente supportate. - {StrBegins="NETSDK1219: "} - NETSDK1131: Producing a managed Windows Metadata component with WinMDExp is not supported when targeting {0}. NETSDK1131: la produzione di un componente Metadati Windows gestito con WinMDExp non è supportata quando la destinazione è {0}. diff --git a/src/Tasks/Common/Resources/xlf/Strings.ja.xlf b/src/Tasks/Common/Resources/xlf/Strings.ja.xlf index 2098ed8a25df..2763c883faa8 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.ja.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.ja.xlf @@ -1033,11 +1033,6 @@ The following are names of parameters or literal values and should not be transl NETSDK1057: プレビュー版の .NET を使用しています。https://aka.ms/dotnet-support-policy をご覧ください {StrBegins="NETSDK1057: "} - - NETSDK1219: UseUwp and all associated functionality are currently experimental and not officially supported. - NETSDK1219: UseUwp および関連するすべての機能は現在試験段階であり、正式にはサポートされていません。 - {StrBegins="NETSDK1219: "} - NETSDK1131: Producing a managed Windows Metadata component with WinMDExp is not supported when targeting {0}. NETSDK1131: {0} をターゲットにする場合、WinMDExp を使用したマネージド Windows メタデータ コンポーネント生成はサポートされていません。 diff --git a/src/Tasks/Common/Resources/xlf/Strings.ko.xlf b/src/Tasks/Common/Resources/xlf/Strings.ko.xlf index 81883f27da98..5c4a7f678d5b 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.ko.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.ko.xlf @@ -1033,11 +1033,6 @@ The following are names of parameters or literal values and should not be transl NETSDK1057: .NET의 미리 보기 버전을 사용하고 있습니다. 참조: https://aka.ms/dotnet-support-policy {StrBegins="NETSDK1057: "} - - NETSDK1219: UseUwp and all associated functionality are currently experimental and not officially supported. - NETSDK1219: UseUwp와 관련된 모든 기능은 현재 실험 상태이며 공식적으로 지원되지 않습니다. - {StrBegins="NETSDK1219: "} - NETSDK1131: Producing a managed Windows Metadata component with WinMDExp is not supported when targeting {0}. NETSDK1131: {0}을(를) 대상으로 지정하는 경우 WinMDExp로 관리형 Windows 메타데이터 구성 요소를 생성하는 것은 지원되지 않습니다. diff --git a/src/Tasks/Common/Resources/xlf/Strings.pl.xlf b/src/Tasks/Common/Resources/xlf/Strings.pl.xlf index 60213f327eba..847799ff9806 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.pl.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.pl.xlf @@ -1033,11 +1033,6 @@ The following are names of parameters or literal values and should not be transl NETSDK1057: Korzystasz z wersji zapoznawczej platformy .NET. Zobacz: ttps://aka.ms/dotnet-support-policy {StrBegins="NETSDK1057: "} - - NETSDK1219: UseUwp and all associated functionality are currently experimental and not officially supported. - NETSDK1219: protokół UseUwp i wszystkie skojarzone funkcje są obecnie eksperymentalne i nie są oficjalnie obsługiwane. - {StrBegins="NETSDK1219: "} - NETSDK1131: Producing a managed Windows Metadata component with WinMDExp is not supported when targeting {0}. NETSDK1131: Generowanie zarządzanego składnika metadanych systemu Windows za pomocą narzędzia WinMDExp nie jest obsługiwane, gdy używany jest element docelowy {0}. diff --git a/src/Tasks/Common/Resources/xlf/Strings.pt-BR.xlf b/src/Tasks/Common/Resources/xlf/Strings.pt-BR.xlf index f2f9ab663c41..f9f0fd16d51c 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.pt-BR.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.pt-BR.xlf @@ -1033,11 +1033,6 @@ The following are names of parameters or literal values and should not be transl NETSDK1057: Você está usando uma versão de visualização do .NET. Veja: https://aka.ms/dotnet-support-policy {StrBegins="NETSDK1057: "} - - NETSDK1219: UseUwp and all associated functionality are currently experimental and not officially supported. - NETSDK1219: UseUwp e todas as funcionalidades associadas atualmente são experimentais e não têm suporte oficial. - {StrBegins="NETSDK1219: "} - NETSDK1131: Producing a managed Windows Metadata component with WinMDExp is not supported when targeting {0}. NETSDK1131: não há suporte para a produção de um componente de Metadados do Windows gerenciado com o WinMDExp ao direcionar ao {0}. diff --git a/src/Tasks/Common/Resources/xlf/Strings.ru.xlf b/src/Tasks/Common/Resources/xlf/Strings.ru.xlf index 8991f7c09817..7770f64b31fc 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.ru.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.ru.xlf @@ -1033,11 +1033,6 @@ The following are names of parameters or literal values and should not be transl NETSDK1057: You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy {StrBegins="NETSDK1057: "} - - NETSDK1219: UseUwp and all associated functionality are currently experimental and not officially supported. - NETSDK1219: UseUwp и все связанные функции на данный момент являются экспериментальными и официально не поддерживаются. - {StrBegins="NETSDK1219: "} - NETSDK1131: Producing a managed Windows Metadata component with WinMDExp is not supported when targeting {0}. NETSDK1131: Producing a managed Windows Metadata component with WinMDExp is not supported when targeting {0}. diff --git a/src/Tasks/Common/Resources/xlf/Strings.tr.xlf b/src/Tasks/Common/Resources/xlf/Strings.tr.xlf index 5dd830aee234..0b6f7aa60b32 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.tr.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.tr.xlf @@ -1033,11 +1033,6 @@ The following are names of parameters or literal values and should not be transl NETSDK1057: Bir .NET önizleme sürümü kullanıyorsunuz. Bkz. https://aka.ms/dotnet-support-policy {StrBegins="NETSDK1057: "} - - NETSDK1219: UseUwp and all associated functionality are currently experimental and not officially supported. - NETSDK1219: UseUwp ve ilişkili tüm işlevler şu anda deneyseldir ve resmi olarak desteklenmez. - {StrBegins="NETSDK1219: "} - NETSDK1131: Producing a managed Windows Metadata component with WinMDExp is not supported when targeting {0}. NETSDK1131: {0} hedeflenirken, WinMDExp ile yönetilen bir Windows Meta Veri bileşeninin üretilmesi desteklenmiyor. diff --git a/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf b/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf index 2fd1f72f629e..e1037cfdecad 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf @@ -1033,11 +1033,6 @@ The following are names of parameters or literal values and should not be transl NETSDK1057: 你正在使用 .NET 的预览版。请参阅 https://aka.ms/dotnet-support-policy {StrBegins="NETSDK1057: "} - - NETSDK1219: UseUwp and all associated functionality are currently experimental and not officially supported. - NETSDK1219: UseUwp 和所有关联的功能目前都是试验性的,并且不受官方支持。 - {StrBegins="NETSDK1219: "} - NETSDK1131: Producing a managed Windows Metadata component with WinMDExp is not supported when targeting {0}. NETSDK1131: 当目标为 {0} 时,不支持使用 WinMDExp 生成托管 Windows 元数据组件。 diff --git a/src/Tasks/Common/Resources/xlf/Strings.zh-Hant.xlf b/src/Tasks/Common/Resources/xlf/Strings.zh-Hant.xlf index 9085e387657e..61f0302195c7 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.zh-Hant.xlf @@ -1033,11 +1033,6 @@ The following are names of parameters or literal values and should not be transl NETSDK1057: 您目前使用的是 .NET 預覽版。請參閱: https://aka.ms/dotnet-support-policy {StrBegins="NETSDK1057: "} - - NETSDK1219: UseUwp and all associated functionality are currently experimental and not officially supported. - NETSDK1219: UseUwp 和所有相關聯的功能目前為實驗性功能,並未正式支援。 - {StrBegins="NETSDK1219: "} - NETSDK1131: Producing a managed Windows Metadata component with WinMDExp is not supported when targeting {0}. NETSDK1131: 當目標為 {0} 時,無法使用 WinMDExp 產生受控 Windows 中繼資料元件。 diff --git a/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenThatWeHaveErrorCodes.cs b/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenThatWeHaveErrorCodes.cs index 7fa45e680dd9..51b35793ffa5 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenThatWeHaveErrorCodes.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenThatWeHaveErrorCodes.cs @@ -39,7 +39,8 @@ public class GivenThatWeHaveErrorCodes 1190, 1192, 1213, - 1214 + 1214, + 1219 }; //ILLink lives in other repos and violated the _info requirement for no error code diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/DependencyContextBuilder.cs b/src/Tasks/Microsoft.NET.Build.Tasks/DependencyContextBuilder.cs index 1f1c4c4a14d8..b50b6935d8ed 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/DependencyContextBuilder.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/DependencyContextBuilder.cs @@ -22,7 +22,6 @@ internal class DependencyContextBuilder private Dictionary> _compileReferences; private Dictionary> _resolvedNuGetFiles; private Dictionary _referenceProjectInfos; - private IEnumerable _excludeFromPublishPackageIds; private Dictionary> _runtimePackAssets; private CompilationOptions _compilationOptions; private string _referenceAssembliesPath; @@ -205,12 +204,6 @@ public DependencyContextBuilder WithReferenceProjectInfos(Dictionary excludeFromPublishPackageIds) - { - _excludeFromPublishPackageIds = excludeFromPublishPackageIds; - return this; - } - public DependencyContextBuilder WithMainProjectInDepsFile(bool includeMainProjectInDepsFile) { _includeMainProjectInDepsFile = includeMainProjectInDepsFile; @@ -537,12 +530,10 @@ private RuntimeLibrary GetRuntimeLibrary(DependencyLibrary library, string[] use { var fileName = Path.GetFileNameWithoutExtension(library.Path); var assemblyPath = userRuntimeAssemblies?.FirstOrDefault(p => Path.GetFileNameWithoutExtension(p).Equals(fileName)); - runtimeAssemblyGroups.Add(new RuntimeAssetGroup(string.Empty, - [ new RuntimeFile( - referenceProjectInfo.OutputName, - library.Version.ToString(), - assemblyPath is null || !File.Exists(assemblyPath) ? string.Empty : FileVersionInfo.GetVersionInfo(assemblyPath).FileVersion) - ])); + var runtimeFile = !string.IsNullOrWhiteSpace(assemblyPath) && File.Exists(assemblyPath) ? CreateRuntimeFile(referenceProjectInfo.OutputName, assemblyPath) : + !string.IsNullOrWhiteSpace(library.Path) && File.Exists(library.Path) ? CreateRuntimeFile(referenceProjectInfo.OutputName, library.Path) : + new RuntimeFile(referenceProjectInfo.OutputName, string.Empty, string.Empty); + runtimeAssemblyGroups.Add(new RuntimeAssetGroup(string.Empty, [runtimeFile])); resourceAssemblies.AddRange(referenceProjectInfo.ResourceAssemblies .Select(r => new ResourceAssembly(r.RelativePath, r.Culture))); @@ -821,37 +812,6 @@ private void CalculateExcludedLibraries() { _dependencyLibraries[packageToExcludeFromRuntime].ExcludeFromRuntime = true; } - - // Include transitive dependencies of all top-level dependencies - Dictionary includedDependencies = new(StringComparer.OrdinalIgnoreCase); - Stack dependencyListToWalk = new(_mainProjectDependencies); - - while (dependencyListToWalk.Count != 0) - { - var dependencyName = dependencyListToWalk.Pop(); - // There may not be a library in the assets file if a referenced project has - // PrivateAssets="all" for a package reference, and there is a package in the graph - // that depends on the same package. - if (!includedDependencies.ContainsKey(dependencyName) && - _excludeFromPublishPackageIds?.Contains(dependencyName) != true && - _dependencyLibraries.TryGetValue(dependencyName, out var dependencyLibrary)) - { - includedDependencies.Add(dependencyName, dependencyLibrary); - foreach (var newDependency in _libraryDependencies[dependencyName]) - { - dependencyListToWalk.Push(newDependency.Name); - } - } - } - - foreach (var dependencyLibrary in _dependencyLibraries.Values) - { - if (!includedDependencies.ContainsKey(dependencyLibrary.Name)) - { - dependencyLibrary.ExcludeFromCompilation = true; - dependencyLibrary.ExcludeFromRuntime = true; - } - } } private string GetReferenceLibraryName(ReferenceInfo reference) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.cs b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.cs new file mode 100644 index 000000000000..558ea870e41c --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.cs @@ -0,0 +1,182 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using global::NuGet.Frameworks; +using global::NuGet.Versioning; + +/// +/// Represents a set of packages that are provided by a specific framework. +/// At the moment this only represents the packages that are provided by the Microsoft.NETCore.App framework. +/// We could extend this to represent the packages provided by other frameworks like Microsoft.AspNetCore.App and Microsoft.WindowsDesktop.App. +/// +internal sealed partial class FrameworkPackages : IEnumerable>, IEnumerable +{ + private const string DefaultFrameworkKey = ""; + private static readonly ConcurrentDictionary> FrameworkPackagesByFramework = []; + + static FrameworkPackages() + { + NETStandard20.Register(); + NETStandard21.Register(); + NET461.Register(); + NETCoreApp20.Register(); + NETCoreApp21.Register(); + NETCoreApp22.Register(); + NETCoreApp30.Register(); + NETCoreApp31.Register(); + NETCoreApp50.Register(); + NETCoreApp60.Register(); + NETCoreApp70.Register(); + NETCoreApp80.Register(); + NETCoreApp90.Register(); + } + + public FrameworkPackages(NuGetFramework framework, string frameworkName) + { + this.Framework = framework; + this.FrameworkName = frameworkName; + } + + public FrameworkPackages(NuGetFramework framework, string frameworkName, FrameworkPackages frameworkPackages) + : this(framework, frameworkName) => this.Packages = new(frameworkPackages.Packages); + + public NuGetFramework Framework { get; } + + public string FrameworkName { get; } + + public Dictionary Packages { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); + + private static string GetFrameworkKey(string frameworkName) => + frameworkName switch + { + FrameworkNames.NetStandardLibrary => DefaultFrameworkKey, + FrameworkNames.NetCoreApp => DefaultFrameworkKey, + _ => frameworkName, + }; + + internal static void Register(params FrameworkPackages[] toRegister) + { + foreach (var frameworkPackages in toRegister) + { + if (!FrameworkPackagesByFramework.TryGetValue(frameworkPackages.Framework, out var frameworkPackagesForVersion)) + { + FrameworkPackagesByFramework[frameworkPackages.Framework] = frameworkPackagesForVersion = []; + } + + var frameworkKey = GetFrameworkKey(frameworkPackages.FrameworkName); + frameworkPackagesForVersion[frameworkKey] = frameworkPackages; + } + } + + public static FrameworkPackages[] GetFrameworkPackages(NuGetFramework framework, string[] frameworkReferences, string targetingPackRoot) + { + var frameworkPackages = new List(); + + if (frameworkReferences.Length == 0) + { + frameworkReferences = [DefaultFrameworkKey]; + } + + foreach (var frameworkReference in frameworkReferences) + { + var frameworkKey = GetFrameworkKey(frameworkReference); + if (FrameworkPackagesByFramework.TryGetValue(framework, out var frameworkPackagesForVersion) && + frameworkPackagesForVersion.TryGetValue(frameworkKey, out var frameworkPackage)) + { + frameworkPackages.Add(frameworkPackage); + } + else + { + // if we didn't predefine the package overrides, load them from the targeting pack + // we might just leave this out since in future frameworks we'll have this functionality built into NuGet.Frameworks + var frameworkPackagesFromPack = LoadFrameworkPackagesFromPack(framework, frameworkReference, targetingPackRoot) ?? new FrameworkPackages(framework, frameworkReference); + + Register(frameworkPackagesFromPack); + + frameworkPackages.Add(frameworkPackagesFromPack); + } + } + + return frameworkPackages.ToArray(); + } + + private static FrameworkPackages LoadFrameworkPackagesFromPack(NuGetFramework framework, string frameworkName, string targetingPackRoot) + { + if (framework is null || framework.Framework != FrameworkConstants.FrameworkIdentifiers.NetCoreApp) + { + return null; + } + + var reducer = new FrameworkReducer(); + var frameworkKey = GetFrameworkKey(frameworkName); + var candidateFrameworks = FrameworkPackagesByFramework.Where(pair => pair.Value.ContainsKey(frameworkKey)).Select(pair => pair.Key); + var nearestFramework = reducer.GetNearest(framework, candidateFrameworks); + + var frameworkPackages = nearestFramework is null ? + new FrameworkPackages(framework, frameworkName) : + new FrameworkPackages(framework, frameworkName, FrameworkPackagesByFramework[nearestFramework][frameworkKey]); + + if (!string.IsNullOrEmpty(targetingPackRoot)) + { + var packsFolder = Path.Combine(targetingPackRoot, frameworkName + ".Ref"); + if (Directory.Exists(packsFolder)) + { + var packVersionPattern = $"{framework.Version.Major}.{framework.Version.Minor}.*"; + var packDirectories = Directory.GetDirectories(packsFolder, packVersionPattern); + var packageOverridesFile = packDirectories + .Select(d => (Overrides: Path.Combine(d, "data", "PackageOverrides.txt"), Version: ParseVersion(Path.GetFileName(d)))) + .Where(d => File.Exists(d.Overrides)) + .OrderByDescending(d => d.Version) + .FirstOrDefault().Overrides; + + if (packageOverridesFile is not null) + { + // Adapted from https://github.com/dotnet/sdk/blob/c3a8f72c3a5491c693ff8e49e7406136a12c3040/src/Tasks/Common/ConflictResolution/PackageOverride.cs#L52-L68 + var packageOverrides = File.ReadAllLines(packageOverridesFile); + + foreach (var packageOverride in packageOverrides) + { + var packageOverrideParts = packageOverride.Trim().Split('|'); + + if (packageOverrideParts.Length == 2) + { + var packageId = packageOverrideParts[0]; + var packageVersion = ParseVersion(packageOverrideParts[1]); + + frameworkPackages.Packages[packageId] = packageVersion; + } + } + } + } + } + + return frameworkPackages; + + static NuGetVersion ParseVersion(string versionString) => NuGetVersion.TryParse(versionString, out var version) ? version : null; + } + + private void Add(string id, string version) + { + // intentionally redirect to indexer to allow for overwrite + this.Packages[id] = NuGetVersion.Parse(version); + } + + public bool IsAFrameworkComponent(string id, NuGetVersion version) => this.Packages.TryGetValue(id, out var frameworkPackageVersion) && frameworkPackageVersion >= version; + + IEnumerator> IEnumerable>.GetEnumerator() => this.Packages.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); + + internal static class FrameworkNames + { + public const string AspNetCoreApp = "Microsoft.AspNetCore.App"; + public const string NetCoreApp = "Microsoft.NETCore.App"; + public const string NetStandardLibrary = "NETStandard.Library"; + public const string WindowsDesktopApp = "Microsoft.WindowsDesktop.App"; + } +} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.net461.cs b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.net461.cs new file mode 100644 index 000000000000..0d9214e5f70e --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.net461.cs @@ -0,0 +1,16 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; + +/// +/// Framework packages for .NETFramework,Version=v4.6.1. +/// +internal partial class FrameworkPackages +{ + internal static class NET461 + { + internal static FrameworkPackages Instance { get; } = new(Net461, DefaultFrameworkKey, NETStandard20.Instance); + + internal static void Register() => FrameworkPackages.Register(Instance); + } +} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.net5.0.cs b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.net5.0.cs new file mode 100644 index 000000000000..6b7a63e0a5de --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.net5.0.cs @@ -0,0 +1,201 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; + +/// +/// Framework packages for net5.0. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp50 + { + internal static FrameworkPackages Instance { get; } = new(Net50, FrameworkNames.NetCoreApp, NETCoreApp31.Instance) + { + { "Microsoft.Win32.Registry", "5.0.0" }, + { "System.Collections.Immutable", "5.0.0" }, + { "System.ComponentModel.Annotations", "5.0.0" }, + { "System.Diagnostics.DiagnosticSource", "5.0.0" }, + { "System.Formats.Asn1", "5.0.0" }, + { "System.IO.FileSystem.AccessControl", "5.0.0" }, + { "System.Net.Http.Json", "5.0.0" }, + { "System.Reflection.DispatchProxy", "4.7.1" }, + { "System.Reflection.Metadata", "5.0.0" }, + { "System.Runtime.CompilerServices.Unsafe", "5.0.0" }, + { "System.Security.AccessControl", "5.0.0" }, + { "System.Security.Cryptography.OpenSsl", "5.0.0" }, + { "System.Security.Principal.Windows", "5.0.0" }, + { "System.Text.Encoding.CodePages", "5.0.0" }, + { "System.Text.Encodings.Web", "5.0.0" }, + { "System.Text.Json", "5.0.0" }, + { "System.Threading.Channels", "5.0.0" }, + { "System.Threading.Tasks.Dataflow", "5.0.0" }, + }; + + internal static FrameworkPackages AspNetCore { get; } = new(Net50, FrameworkNames.AspNetCoreApp, NETCoreApp31.AspNetCore) + { + { "Microsoft.AspNetCore", "5.0.0" }, + { "Microsoft.AspNetCore.Antiforgery", "5.0.0" }, + { "Microsoft.AspNetCore.Authentication", "5.0.0" }, + { "Microsoft.AspNetCore.Authentication.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.Authentication.Cookies", "5.0.0" }, + { "Microsoft.AspNetCore.Authentication.Core", "5.0.0" }, + { "Microsoft.AspNetCore.Authentication.OAuth", "5.0.0" }, + { "Microsoft.AspNetCore.Authorization", "5.0.0" }, + { "Microsoft.AspNetCore.Authorization.Policy", "5.0.0" }, + { "Microsoft.AspNetCore.Components", "5.0.0" }, + { "Microsoft.AspNetCore.Components.Authorization", "5.0.0" }, + { "Microsoft.AspNetCore.Components.Forms", "5.0.0" }, + { "Microsoft.AspNetCore.Components.Server", "5.0.0" }, + { "Microsoft.AspNetCore.Components.Web", "5.0.0" }, + { "Microsoft.AspNetCore.Connections.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.CookiePolicy", "5.0.0" }, + { "Microsoft.AspNetCore.Cors", "5.0.0" }, + { "Microsoft.AspNetCore.Cryptography.Internal", "5.0.0" }, + { "Microsoft.AspNetCore.Cryptography.KeyDerivation", "5.0.0" }, + { "Microsoft.AspNetCore.DataProtection", "5.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Extensions", "5.0.0" }, + { "Microsoft.AspNetCore.Diagnostics", "5.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.HealthChecks", "5.0.0" }, + { "Microsoft.AspNetCore.HostFiltering", "5.0.0" }, + { "Microsoft.AspNetCore.Hosting", "5.0.0" }, + { "Microsoft.AspNetCore.Hosting.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.Hosting.Server.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.Html.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.Http", "5.0.0" }, + { "Microsoft.AspNetCore.Http.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.Http.Connections", "5.0.0" }, + { "Microsoft.AspNetCore.Http.Connections.Common", "5.0.0" }, + { "Microsoft.AspNetCore.Http.Extensions", "5.0.0" }, + { "Microsoft.AspNetCore.Http.Features", "5.0.0" }, + { "Microsoft.AspNetCore.HttpOverrides", "5.0.0" }, + { "Microsoft.AspNetCore.HttpsPolicy", "5.0.0" }, + { "Microsoft.AspNetCore.Identity", "5.0.0" }, + { "Microsoft.AspNetCore.Localization", "5.0.0" }, + { "Microsoft.AspNetCore.Localization.Routing", "5.0.0" }, + { "Microsoft.AspNetCore.Metadata", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.ApiExplorer", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.Core", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.Cors", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.DataAnnotations", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Json", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Xml", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.Localization", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.Razor", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.RazorPages", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.TagHelpers", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.ViewFeatures", "5.0.0" }, + { "Microsoft.AspNetCore.Razor", "5.0.0" }, + { "Microsoft.AspNetCore.Razor.Runtime", "5.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching", "5.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.ResponseCompression", "5.0.0" }, + { "Microsoft.AspNetCore.Rewrite", "5.0.0" }, + { "Microsoft.AspNetCore.Routing", "5.0.0" }, + { "Microsoft.AspNetCore.Routing.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.Server.HttpSys", "5.0.0" }, + { "Microsoft.AspNetCore.Server.IIS", "5.0.0" }, + { "Microsoft.AspNetCore.Server.IISIntegration", "5.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel", "5.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Core", "5.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", "5.0.0" }, + { "Microsoft.AspNetCore.Session", "5.0.0" }, + { "Microsoft.AspNetCore.SignalR", "5.0.0" }, + { "Microsoft.AspNetCore.SignalR.Common", "5.0.0" }, + { "Microsoft.AspNetCore.SignalR.Core", "5.0.0" }, + { "Microsoft.AspNetCore.SignalR.Protocols.Json", "5.0.0" }, + { "Microsoft.AspNetCore.StaticFiles", "5.0.0" }, + { "Microsoft.AspNetCore.WebSockets", "5.0.0" }, + { "Microsoft.AspNetCore.WebUtilities", "5.0.0" }, + { "Microsoft.Extensions.Caching.Abstractions", "5.0.0" }, + { "Microsoft.Extensions.Caching.Memory", "5.0.0" }, + { "Microsoft.Extensions.Configuration", "5.0.0" }, + { "Microsoft.Extensions.Configuration.Abstractions", "5.0.0" }, + { "Microsoft.Extensions.Configuration.Binder", "5.0.0" }, + { "Microsoft.Extensions.Configuration.CommandLine", "5.0.0" }, + { "Microsoft.Extensions.Configuration.EnvironmentVariables", "5.0.0" }, + { "Microsoft.Extensions.Configuration.FileExtensions", "5.0.0" }, + { "Microsoft.Extensions.Configuration.Ini", "5.0.0" }, + { "Microsoft.Extensions.Configuration.Json", "5.0.0" }, + { "Microsoft.Extensions.Configuration.KeyPerFile", "5.0.0" }, + { "Microsoft.Extensions.Configuration.UserSecrets", "5.0.0" }, + { "Microsoft.Extensions.Configuration.Xml", "5.0.0" }, + { "Microsoft.Extensions.DependencyInjection", "5.0.0" }, + { "Microsoft.Extensions.DependencyInjection.Abstractions", "5.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks", "5.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "5.0.0" }, + { "Microsoft.Extensions.FileProviders.Abstractions", "5.0.0" }, + { "Microsoft.Extensions.FileProviders.Composite", "5.0.0" }, + { "Microsoft.Extensions.FileProviders.Embedded", "5.0.0" }, + { "Microsoft.Extensions.FileProviders.Physical", "5.0.0" }, + { "Microsoft.Extensions.FileSystemGlobbing", "5.0.0" }, + { "Microsoft.Extensions.Hosting", "5.0.0" }, + { "Microsoft.Extensions.Hosting.Abstractions", "5.0.0" }, + { "Microsoft.Extensions.Http", "5.0.0" }, + { "Microsoft.Extensions.Identity.Core", "5.0.0" }, + { "Microsoft.Extensions.Identity.Stores", "5.0.0" }, + { "Microsoft.Extensions.Localization", "5.0.0" }, + { "Microsoft.Extensions.Localization.Abstractions", "5.0.0" }, + { "Microsoft.Extensions.Logging", "5.0.0" }, + { "Microsoft.Extensions.Logging.Abstractions", "5.0.0" }, + { "Microsoft.Extensions.Logging.Configuration", "5.0.0" }, + { "Microsoft.Extensions.Logging.Console", "5.0.0" }, + { "Microsoft.Extensions.Logging.Debug", "5.0.0" }, + { "Microsoft.Extensions.Logging.EventLog", "5.0.0" }, + { "Microsoft.Extensions.Logging.EventSource", "5.0.0" }, + { "Microsoft.Extensions.Logging.TraceSource", "5.0.0" }, + { "Microsoft.Extensions.ObjectPool", "5.0.0" }, + { "Microsoft.Extensions.Options", "5.0.0" }, + { "Microsoft.Extensions.Options.ConfigurationExtensions", "5.0.0" }, + { "Microsoft.Extensions.Options.DataAnnotations", "5.0.0" }, + { "Microsoft.Extensions.Primitives", "5.0.0" }, + { "Microsoft.Extensions.WebEncoders", "5.0.0" }, + { "Microsoft.JSInterop", "5.0.0" }, + { "Microsoft.Net.Http.Headers", "5.0.0" }, + { "Microsoft.Win32.Registry", "5.0.0" }, + { "Microsoft.Win32.SystemEvents", "5.0.0" }, + { "System.Diagnostics.EventLog", "5.0.0" }, + { "System.Drawing.Common", "5.0.0" }, + { "System.IO.Pipelines", "5.0.0" }, + { "System.Security.AccessControl", "5.0.0" }, + { "System.Security.Cryptography.Cng", "5.0.0" }, + { "System.Security.Cryptography.Pkcs", "5.0.0" }, + { "System.Security.Cryptography.Xml", "5.0.0" }, + { "System.Security.Permissions", "5.0.0" }, + { "System.Security.Principal.Windows", "5.0.0" }, + { "System.Windows.Extensions", "5.0.0" }, + }; + + internal static FrameworkPackages WindowsDesktop { get; } = new(Net50, FrameworkNames.WindowsDesktopApp, NETCoreApp31.WindowsDesktop) + { + { "Microsoft.VisualBasic", "10.3.0" }, + { "Microsoft.Win32.Registry", "5.0.0" }, + { "Microsoft.Win32.Registry.AccessControl", "5.0.0" }, + { "Microsoft.Win32.SystemEvents", "5.0.0" }, + { "System.CodeDom", "5.0.0" }, + { "System.Configuration.ConfigurationManager", "5.0.0" }, + { "System.Diagnostics.EventLog", "5.0.0" }, + { "System.Diagnostics.PerformanceCounter", "5.0.0" }, + { "System.Drawing.Common", "5.0.0" }, + { "System.Formats.Asn1", "5.0.0" }, + { "System.IO.FileSystem.AccessControl", "5.0.0" }, + { "System.IO.Packaging", "5.0.0" }, + { "System.IO.Pipes.AccessControl", "5.0.0" }, + { "System.Resources.Extensions", "5.0.0" }, + { "System.Security.AccessControl", "5.0.0" }, + { "System.Security.Cryptography.Cng", "5.0.0" }, + { "System.Security.Cryptography.Pkcs", "5.0.0" }, + { "System.Security.Cryptography.ProtectedData", "5.0.0" }, + { "System.Security.Cryptography.Xml", "5.0.0" }, + { "System.Security.Permissions", "5.0.0" }, + { "System.Security.Principal.Windows", "5.0.0" }, + { "System.Threading.AccessControl", "5.0.0" }, + { "System.Windows.Extensions", "5.0.0" }, + }; + + internal static void Register() => FrameworkPackages.Register(Instance, AspNetCore, WindowsDesktop); + } +} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.net6.0.cs b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.net6.0.cs new file mode 100644 index 000000000000..dde6aa76815f --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.net6.0.cs @@ -0,0 +1,183 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; + +/// +/// Framework packages for net6.0. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp60 + { + internal static FrameworkPackages Instance { get; } = new(Net60, FrameworkNames.NetCoreApp, NETCoreApp50.Instance) + { + { "System.Collections.Immutable", "6.0.0" }, + { "System.Diagnostics.DiagnosticSource", "6.0.0" }, + { "System.Formats.Asn1", "6.0.0" }, + { "System.Net.Http.Json", "6.0.0" }, + { "System.Reflection.Metadata", "6.0.0" }, + { "System.Runtime.CompilerServices.Unsafe", "6.0.0" }, + { "System.Security.AccessControl", "6.0.0" }, + { "System.Text.Encoding.CodePages", "6.0.0" }, + { "System.Text.Encodings.Web", "6.0.0" }, + { "System.Text.Json", "6.0.0" }, + { "System.Threading.Channels", "6.0.0" }, + { "System.Threading.Tasks.Dataflow", "6.0.0" }, + }; + + internal static FrameworkPackages AspNetCore { get; } = new(Net60, FrameworkNames.AspNetCoreApp, NETCoreApp50.AspNetCore) + { + { "Microsoft.AspNetCore", "6.0.0" }, + { "Microsoft.AspNetCore.Antiforgery", "6.0.0" }, + { "Microsoft.AspNetCore.Authentication", "6.0.0" }, + { "Microsoft.AspNetCore.Authentication.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.Authentication.Cookies", "6.0.0" }, + { "Microsoft.AspNetCore.Authentication.Core", "6.0.0" }, + { "Microsoft.AspNetCore.Authentication.OAuth", "6.0.0" }, + { "Microsoft.AspNetCore.Authorization", "6.0.0" }, + { "Microsoft.AspNetCore.Authorization.Policy", "6.0.0" }, + { "Microsoft.AspNetCore.Components", "6.0.0" }, + { "Microsoft.AspNetCore.Components.Authorization", "6.0.0" }, + { "Microsoft.AspNetCore.Components.Forms", "6.0.0" }, + { "Microsoft.AspNetCore.Components.Server", "6.0.0" }, + { "Microsoft.AspNetCore.Components.Web", "6.0.0" }, + { "Microsoft.AspNetCore.Connections.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.CookiePolicy", "6.0.0" }, + { "Microsoft.AspNetCore.Cors", "6.0.0" }, + { "Microsoft.AspNetCore.Cryptography.Internal", "6.0.0" }, + { "Microsoft.AspNetCore.Cryptography.KeyDerivation", "6.0.0" }, + { "Microsoft.AspNetCore.DataProtection", "6.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Extensions", "6.0.0" }, + { "Microsoft.AspNetCore.Diagnostics", "6.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.HealthChecks", "6.0.0" }, + { "Microsoft.AspNetCore.HostFiltering", "6.0.0" }, + { "Microsoft.AspNetCore.Hosting", "6.0.0" }, + { "Microsoft.AspNetCore.Hosting.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.Hosting.Server.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.Html.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.Http", "6.0.0" }, + { "Microsoft.AspNetCore.Http.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.Http.Connections", "6.0.0" }, + { "Microsoft.AspNetCore.Http.Connections.Common", "6.0.0" }, + { "Microsoft.AspNetCore.Http.Extensions", "6.0.0" }, + { "Microsoft.AspNetCore.Http.Features", "6.0.0" }, + { "Microsoft.AspNetCore.Http.Results", "6.0.0" }, + { "Microsoft.AspNetCore.HttpLogging", "6.0.0" }, + { "Microsoft.AspNetCore.HttpOverrides", "6.0.0" }, + { "Microsoft.AspNetCore.HttpsPolicy", "6.0.0" }, + { "Microsoft.AspNetCore.Identity", "6.0.0" }, + { "Microsoft.AspNetCore.Localization", "6.0.0" }, + { "Microsoft.AspNetCore.Localization.Routing", "6.0.0" }, + { "Microsoft.AspNetCore.Metadata", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.ApiExplorer", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.Core", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.Cors", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.DataAnnotations", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Json", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Xml", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.Localization", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.Razor", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.RazorPages", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.TagHelpers", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.ViewFeatures", "6.0.0" }, + { "Microsoft.AspNetCore.Razor", "6.0.0" }, + { "Microsoft.AspNetCore.Razor.Runtime", "6.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching", "6.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.ResponseCompression", "6.0.0" }, + { "Microsoft.AspNetCore.Rewrite", "6.0.0" }, + { "Microsoft.AspNetCore.Routing", "6.0.0" }, + { "Microsoft.AspNetCore.Routing.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.Server.HttpSys", "6.0.0" }, + { "Microsoft.AspNetCore.Server.IIS", "6.0.0" }, + { "Microsoft.AspNetCore.Server.IISIntegration", "6.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel", "6.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Core", "6.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Quic", "6.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", "6.0.0" }, + { "Microsoft.AspNetCore.Session", "6.0.0" }, + { "Microsoft.AspNetCore.SignalR", "6.0.0" }, + { "Microsoft.AspNetCore.SignalR.Common", "6.0.0" }, + { "Microsoft.AspNetCore.SignalR.Core", "6.0.0" }, + { "Microsoft.AspNetCore.SignalR.Protocols.Json", "6.0.0" }, + { "Microsoft.AspNetCore.StaticFiles", "6.0.0" }, + { "Microsoft.AspNetCore.WebSockets", "6.0.0" }, + { "Microsoft.AspNetCore.WebUtilities", "6.0.0" }, + { "Microsoft.Extensions.Caching.Abstractions", "6.0.0" }, + { "Microsoft.Extensions.Caching.Memory", "6.0.0" }, + { "Microsoft.Extensions.Configuration", "6.0.0" }, + { "Microsoft.Extensions.Configuration.Abstractions", "6.0.0" }, + { "Microsoft.Extensions.Configuration.Binder", "6.0.0" }, + { "Microsoft.Extensions.Configuration.CommandLine", "6.0.0" }, + { "Microsoft.Extensions.Configuration.EnvironmentVariables", "6.0.0" }, + { "Microsoft.Extensions.Configuration.FileExtensions", "6.0.0" }, + { "Microsoft.Extensions.Configuration.Ini", "6.0.0" }, + { "Microsoft.Extensions.Configuration.Json", "6.0.0" }, + { "Microsoft.Extensions.Configuration.KeyPerFile", "6.0.0" }, + { "Microsoft.Extensions.Configuration.UserSecrets", "6.0.0" }, + { "Microsoft.Extensions.Configuration.Xml", "6.0.0" }, + { "Microsoft.Extensions.DependencyInjection", "6.0.0" }, + { "Microsoft.Extensions.DependencyInjection.Abstractions", "6.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks", "6.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "6.0.0" }, + { "Microsoft.Extensions.Features", "6.0.0" }, + { "Microsoft.Extensions.FileProviders.Abstractions", "6.0.0" }, + { "Microsoft.Extensions.FileProviders.Composite", "6.0.0" }, + { "Microsoft.Extensions.FileProviders.Embedded", "6.0.0" }, + { "Microsoft.Extensions.FileProviders.Physical", "6.0.0" }, + { "Microsoft.Extensions.FileSystemGlobbing", "6.0.0" }, + { "Microsoft.Extensions.Hosting", "6.0.0" }, + { "Microsoft.Extensions.Hosting.Abstractions", "6.0.0" }, + { "Microsoft.Extensions.Http", "6.0.0" }, + { "Microsoft.Extensions.Identity.Core", "6.0.0" }, + { "Microsoft.Extensions.Identity.Stores", "6.0.0" }, + { "Microsoft.Extensions.Localization", "6.0.0" }, + { "Microsoft.Extensions.Localization.Abstractions", "6.0.0" }, + { "Microsoft.Extensions.Logging", "6.0.0" }, + { "Microsoft.Extensions.Logging.Abstractions", "6.0.0" }, + { "Microsoft.Extensions.Logging.Configuration", "6.0.0" }, + { "Microsoft.Extensions.Logging.Console", "6.0.0" }, + { "Microsoft.Extensions.Logging.Debug", "6.0.0" }, + { "Microsoft.Extensions.Logging.EventLog", "6.0.0" }, + { "Microsoft.Extensions.Logging.EventSource", "6.0.0" }, + { "Microsoft.Extensions.Logging.TraceSource", "6.0.0" }, + { "Microsoft.Extensions.ObjectPool", "6.0.0" }, + { "Microsoft.Extensions.Options", "6.0.0" }, + { "Microsoft.Extensions.Options.ConfigurationExtensions", "6.0.0" }, + { "Microsoft.Extensions.Options.DataAnnotations", "6.0.0" }, + { "Microsoft.Extensions.Primitives", "6.0.0" }, + { "Microsoft.Extensions.WebEncoders", "6.0.0" }, + { "Microsoft.JSInterop", "6.0.0" }, + { "Microsoft.Net.Http.Headers", "6.0.0" }, + { "System.Diagnostics.EventLog", "6.0.0" }, + { "System.IO.Pipelines", "6.0.0" }, + { "System.Security.Cryptography.Pkcs", "6.0.0" }, + { "System.Security.Cryptography.Xml", "6.0.0" }, + }; + + internal static FrameworkPackages WindowsDesktop { get; } = new(Net60, FrameworkNames.WindowsDesktopApp, NETCoreApp50.WindowsDesktop) + { + { "Microsoft.Win32.Registry.AccessControl", "6.0.0" }, + { "Microsoft.Win32.SystemEvents", "6.0.0" }, + { "System.CodeDom", "6.0.0" }, + { "System.Configuration.ConfigurationManager", "6.0.0" }, + { "System.Diagnostics.EventLog", "6.0.0" }, + { "System.Diagnostics.PerformanceCounter", "6.0.0" }, + { "System.Drawing.Common", "6.0.0" }, + { "System.IO.Packaging", "6.0.0" }, + { "System.Resources.Extensions", "6.0.0" }, + { "System.Security.Cryptography.Pkcs", "6.0.0" }, + { "System.Security.Cryptography.ProtectedData", "6.0.0" }, + { "System.Security.Cryptography.Xml", "6.0.0" }, + { "System.Security.Permissions", "6.0.0" }, + { "System.Threading.AccessControl", "6.0.0" }, + { "System.Windows.Extensions", "6.0.0" }, + }; + + internal static void Register() => FrameworkPackages.Register(Instance, AspNetCore, WindowsDesktop); + } +} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.net7.0.cs b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.net7.0.cs new file mode 100644 index 000000000000..4e8d49af3f8e --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.net7.0.cs @@ -0,0 +1,186 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; + +/// +/// Framework packages for net7.0. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp70 + { + internal static FrameworkPackages Instance { get; } = new(Net70, FrameworkNames.NetCoreApp, NETCoreApp60.Instance) + { + { "System.Collections.Immutable", "7.0.0" }, + { "System.Diagnostics.DiagnosticSource", "7.0.2" }, + { "System.Formats.Asn1", "7.0.0" }, + { "System.Net.Http.Json", "7.0.1" }, + { "System.Reflection.Metadata", "7.0.2" }, + { "System.Security.AccessControl", "6.0.1" }, + { "System.Text.Encoding.CodePages", "7.0.0" }, + { "System.Text.Encodings.Web", "7.0.0" }, + { "System.Text.Json", "7.0.4" }, + { "System.Threading.Channels", "7.0.0" }, + { "System.Threading.Tasks.Dataflow", "7.0.0" }, + }; + + internal static FrameworkPackages AspNetCore { get; } = new(Net70, FrameworkNames.AspNetCoreApp, NETCoreApp60.AspNetCore) + { + { "Microsoft.AspNetCore", "7.0.0" }, + { "Microsoft.AspNetCore.Antiforgery", "7.0.0" }, + { "Microsoft.AspNetCore.Authentication", "7.0.0" }, + { "Microsoft.AspNetCore.Authentication.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.Authentication.Cookies", "7.0.0" }, + { "Microsoft.AspNetCore.Authentication.Core", "7.0.0" }, + { "Microsoft.AspNetCore.Authentication.OAuth", "7.0.0" }, + { "Microsoft.AspNetCore.Authorization", "7.0.0" }, + { "Microsoft.AspNetCore.Authorization.Policy", "7.0.0" }, + { "Microsoft.AspNetCore.Components", "7.0.0" }, + { "Microsoft.AspNetCore.Components.Authorization", "7.0.0" }, + { "Microsoft.AspNetCore.Components.Forms", "7.0.0" }, + { "Microsoft.AspNetCore.Components.Server", "7.0.0" }, + { "Microsoft.AspNetCore.Components.Web", "7.0.0" }, + { "Microsoft.AspNetCore.Connections.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.CookiePolicy", "7.0.0" }, + { "Microsoft.AspNetCore.Cors", "7.0.0" }, + { "Microsoft.AspNetCore.Cryptography.Internal", "7.0.0" }, + { "Microsoft.AspNetCore.Cryptography.KeyDerivation", "7.0.0" }, + { "Microsoft.AspNetCore.DataProtection", "7.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Extensions", "7.0.0" }, + { "Microsoft.AspNetCore.Diagnostics", "7.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.HealthChecks", "7.0.0" }, + { "Microsoft.AspNetCore.HostFiltering", "7.0.0" }, + { "Microsoft.AspNetCore.Hosting", "7.0.0" }, + { "Microsoft.AspNetCore.Hosting.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.Hosting.Server.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.Html.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.Http", "7.0.0" }, + { "Microsoft.AspNetCore.Http.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.Http.Connections", "7.0.0" }, + { "Microsoft.AspNetCore.Http.Connections.Common", "7.0.0" }, + { "Microsoft.AspNetCore.Http.Extensions", "7.0.0" }, + { "Microsoft.AspNetCore.Http.Features", "7.0.0" }, + { "Microsoft.AspNetCore.Http.Results", "7.0.0" }, + { "Microsoft.AspNetCore.HttpLogging", "7.0.0" }, + { "Microsoft.AspNetCore.HttpOverrides", "7.0.0" }, + { "Microsoft.AspNetCore.HttpsPolicy", "7.0.0" }, + { "Microsoft.AspNetCore.Identity", "7.0.0" }, + { "Microsoft.AspNetCore.Localization", "7.0.0" }, + { "Microsoft.AspNetCore.Localization.Routing", "7.0.0" }, + { "Microsoft.AspNetCore.Metadata", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.ApiExplorer", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.Core", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.Cors", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.DataAnnotations", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Json", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Xml", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.Localization", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.Razor", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.RazorPages", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.TagHelpers", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.ViewFeatures", "7.0.0" }, + { "Microsoft.AspNetCore.OutputCaching", "7.0.0" }, + { "Microsoft.AspNetCore.RateLimiting", "7.0.0" }, + { "Microsoft.AspNetCore.Razor", "7.0.0" }, + { "Microsoft.AspNetCore.Razor.Runtime", "7.0.0" }, + { "Microsoft.AspNetCore.RequestDecompression", "7.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching", "7.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.ResponseCompression", "7.0.0" }, + { "Microsoft.AspNetCore.Rewrite", "7.0.0" }, + { "Microsoft.AspNetCore.Routing", "7.0.0" }, + { "Microsoft.AspNetCore.Routing.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.Server.HttpSys", "7.0.0" }, + { "Microsoft.AspNetCore.Server.IIS", "7.0.0" }, + { "Microsoft.AspNetCore.Server.IISIntegration", "7.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel", "7.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Core", "7.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Quic", "7.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", "7.0.0" }, + { "Microsoft.AspNetCore.Session", "7.0.0" }, + { "Microsoft.AspNetCore.SignalR", "7.0.0" }, + { "Microsoft.AspNetCore.SignalR.Common", "7.0.0" }, + { "Microsoft.AspNetCore.SignalR.Core", "7.0.0" }, + { "Microsoft.AspNetCore.SignalR.Protocols.Json", "7.0.0" }, + { "Microsoft.AspNetCore.StaticFiles", "7.0.0" }, + { "Microsoft.AspNetCore.WebSockets", "7.0.0" }, + { "Microsoft.AspNetCore.WebUtilities", "7.0.0" }, + { "Microsoft.Extensions.Caching.Abstractions", "7.0.0" }, + { "Microsoft.Extensions.Caching.Memory", "7.0.0" }, + { "Microsoft.Extensions.Configuration", "7.0.0" }, + { "Microsoft.Extensions.Configuration.Abstractions", "7.0.0" }, + { "Microsoft.Extensions.Configuration.Binder", "7.0.0" }, + { "Microsoft.Extensions.Configuration.CommandLine", "7.0.0" }, + { "Microsoft.Extensions.Configuration.EnvironmentVariables", "7.0.0" }, + { "Microsoft.Extensions.Configuration.FileExtensions", "7.0.0" }, + { "Microsoft.Extensions.Configuration.Ini", "7.0.0" }, + { "Microsoft.Extensions.Configuration.Json", "7.0.0" }, + { "Microsoft.Extensions.Configuration.KeyPerFile", "7.0.0" }, + { "Microsoft.Extensions.Configuration.UserSecrets", "7.0.0" }, + { "Microsoft.Extensions.Configuration.Xml", "7.0.0" }, + { "Microsoft.Extensions.DependencyInjection", "7.0.0" }, + { "Microsoft.Extensions.DependencyInjection.Abstractions", "7.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks", "7.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "7.0.0" }, + { "Microsoft.Extensions.Features", "7.0.0" }, + { "Microsoft.Extensions.FileProviders.Abstractions", "7.0.0" }, + { "Microsoft.Extensions.FileProviders.Composite", "7.0.0" }, + { "Microsoft.Extensions.FileProviders.Embedded", "7.0.0" }, + { "Microsoft.Extensions.FileProviders.Physical", "7.0.0" }, + { "Microsoft.Extensions.FileSystemGlobbing", "7.0.0" }, + { "Microsoft.Extensions.Hosting", "7.0.0" }, + { "Microsoft.Extensions.Hosting.Abstractions", "7.0.0" }, + { "Microsoft.Extensions.Http", "7.0.0" }, + { "Microsoft.Extensions.Identity.Core", "7.0.0" }, + { "Microsoft.Extensions.Identity.Stores", "7.0.0" }, + { "Microsoft.Extensions.Localization", "7.0.0" }, + { "Microsoft.Extensions.Localization.Abstractions", "7.0.0" }, + { "Microsoft.Extensions.Logging", "7.0.0" }, + { "Microsoft.Extensions.Logging.Abstractions", "7.0.0" }, + { "Microsoft.Extensions.Logging.Configuration", "7.0.0" }, + { "Microsoft.Extensions.Logging.Console", "7.0.0" }, + { "Microsoft.Extensions.Logging.Debug", "7.0.0" }, + { "Microsoft.Extensions.Logging.EventLog", "7.0.0" }, + { "Microsoft.Extensions.Logging.EventSource", "7.0.0" }, + { "Microsoft.Extensions.Logging.TraceSource", "7.0.0" }, + { "Microsoft.Extensions.ObjectPool", "7.0.0" }, + { "Microsoft.Extensions.Options", "7.0.0" }, + { "Microsoft.Extensions.Options.ConfigurationExtensions", "7.0.0" }, + { "Microsoft.Extensions.Options.DataAnnotations", "7.0.0" }, + { "Microsoft.Extensions.Primitives", "7.0.0" }, + { "Microsoft.Extensions.WebEncoders", "7.0.0" }, + { "Microsoft.JSInterop", "7.0.0" }, + { "Microsoft.Net.Http.Headers", "7.0.0" }, + { "System.Diagnostics.EventLog", "7.0.0" }, + { "System.IO.Pipelines", "7.0.0" }, + { "System.Security.Cryptography.Pkcs", "7.0.0" }, + { "System.Security.Cryptography.Xml", "7.0.0" }, + { "System.Threading.RateLimiting", "7.0.0" }, + }; + + internal static FrameworkPackages WindowsDesktop { get; } = new(Net70, FrameworkNames.WindowsDesktopApp, NETCoreApp60.WindowsDesktop) + { + { "Microsoft.Win32.Registry.AccessControl", "7.0.0" }, + { "Microsoft.Win32.SystemEvents", "7.0.0" }, + { "System.CodeDom", "7.0.0" }, + { "System.Configuration.ConfigurationManager", "7.0.0" }, + { "System.Diagnostics.EventLog", "7.0.0" }, + { "System.Diagnostics.PerformanceCounter", "7.0.0" }, + { "System.Drawing.Common", "7.0.0" }, + { "System.IO.Packaging", "7.0.0" }, + { "System.Resources.Extensions", "7.0.0" }, + { "System.Security.Cryptography.Pkcs", "7.0.0" }, + { "System.Security.Cryptography.ProtectedData", "7.0.0" }, + { "System.Security.Cryptography.Xml", "7.0.0" }, + { "System.Security.Permissions", "7.0.0" }, + { "System.Threading.AccessControl", "7.0.0" }, + { "System.Windows.Extensions", "7.0.0" }, + }; + + internal static void Register() => FrameworkPackages.Register(Instance, AspNetCore, WindowsDesktop); + } +} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.net8.0.cs b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.net8.0.cs new file mode 100644 index 000000000000..f329bcdf7aac --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.net8.0.cs @@ -0,0 +1,190 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; + +/// +/// Framework packages for net8.0. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp80 + { + internal static FrameworkPackages Instance { get; } = new(Net80, FrameworkNames.NetCoreApp, NETCoreApp70.Instance) + { + { "System.Collections.Immutable", "8.0.0" }, + { "System.Diagnostics.DiagnosticSource", "8.0.1" }, + { "System.Formats.Asn1", "8.0.1" }, + { "System.Net.Http.Json", "8.0.1" }, + { "System.Reflection.Metadata", "8.0.1" }, + { "System.Text.Encoding.CodePages", "8.0.0" }, + { "System.Text.Encodings.Web", "8.0.0" }, + { "System.Text.Json", "8.0.5" }, + { "System.Threading.Channels", "8.0.0" }, + { "System.Threading.Tasks.Dataflow", "8.0.1" }, + }; + + internal static FrameworkPackages AspNetCore { get; } = new(Net80, FrameworkNames.AspNetCoreApp, NETCoreApp70.AspNetCore) + { + { "Microsoft.AspNetCore", "8.0.0" }, + { "Microsoft.AspNetCore.Antiforgery", "8.0.0" }, + { "Microsoft.AspNetCore.Authentication", "8.0.0" }, + { "Microsoft.AspNetCore.Authentication.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.Authentication.BearerToken", "8.0.0" }, + { "Microsoft.AspNetCore.Authentication.Cookies", "8.0.0" }, + { "Microsoft.AspNetCore.Authentication.Core", "8.0.0" }, + { "Microsoft.AspNetCore.Authentication.OAuth", "8.0.0" }, + { "Microsoft.AspNetCore.Authorization", "8.0.0" }, + { "Microsoft.AspNetCore.Authorization.Policy", "8.0.0" }, + { "Microsoft.AspNetCore.Components", "8.0.0" }, + { "Microsoft.AspNetCore.Components.Authorization", "8.0.0" }, + { "Microsoft.AspNetCore.Components.Endpoints", "8.0.0" }, + { "Microsoft.AspNetCore.Components.Forms", "8.0.0" }, + { "Microsoft.AspNetCore.Components.Server", "8.0.0" }, + { "Microsoft.AspNetCore.Components.Web", "8.0.0" }, + { "Microsoft.AspNetCore.Connections.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.CookiePolicy", "8.0.0" }, + { "Microsoft.AspNetCore.Cors", "8.0.0" }, + { "Microsoft.AspNetCore.Cryptography.Internal", "8.0.0" }, + { "Microsoft.AspNetCore.Cryptography.KeyDerivation", "8.0.0" }, + { "Microsoft.AspNetCore.DataProtection", "8.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Extensions", "8.0.0" }, + { "Microsoft.AspNetCore.Diagnostics", "8.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.HealthChecks", "8.0.0" }, + { "Microsoft.AspNetCore.HostFiltering", "8.0.0" }, + { "Microsoft.AspNetCore.Hosting", "8.0.0" }, + { "Microsoft.AspNetCore.Hosting.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.Hosting.Server.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.Html.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.Http", "8.0.0" }, + { "Microsoft.AspNetCore.Http.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.Http.Connections", "8.0.0" }, + { "Microsoft.AspNetCore.Http.Connections.Common", "8.0.0" }, + { "Microsoft.AspNetCore.Http.Extensions", "8.0.0" }, + { "Microsoft.AspNetCore.Http.Features", "8.0.0" }, + { "Microsoft.AspNetCore.Http.Results", "8.0.0" }, + { "Microsoft.AspNetCore.HttpLogging", "8.0.0" }, + { "Microsoft.AspNetCore.HttpOverrides", "8.0.0" }, + { "Microsoft.AspNetCore.HttpsPolicy", "8.0.0" }, + { "Microsoft.AspNetCore.Identity", "8.0.0" }, + { "Microsoft.AspNetCore.Localization", "8.0.0" }, + { "Microsoft.AspNetCore.Localization.Routing", "8.0.0" }, + { "Microsoft.AspNetCore.Metadata", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.ApiExplorer", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.Core", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.Cors", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.DataAnnotations", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Json", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Xml", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.Localization", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.Razor", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.RazorPages", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.TagHelpers", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.ViewFeatures", "8.0.0" }, + { "Microsoft.AspNetCore.OutputCaching", "8.0.0" }, + { "Microsoft.AspNetCore.RateLimiting", "8.0.0" }, + { "Microsoft.AspNetCore.Razor", "8.0.0" }, + { "Microsoft.AspNetCore.Razor.Runtime", "8.0.0" }, + { "Microsoft.AspNetCore.RequestDecompression", "8.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching", "8.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.ResponseCompression", "8.0.0" }, + { "Microsoft.AspNetCore.Rewrite", "8.0.0" }, + { "Microsoft.AspNetCore.Routing", "8.0.0" }, + { "Microsoft.AspNetCore.Routing.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.Server.HttpSys", "8.0.0" }, + { "Microsoft.AspNetCore.Server.IIS", "8.0.0" }, + { "Microsoft.AspNetCore.Server.IISIntegration", "8.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel", "8.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Core", "8.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.NamedPipes", "8.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Quic", "8.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", "8.0.0" }, + { "Microsoft.AspNetCore.Session", "8.0.0" }, + { "Microsoft.AspNetCore.SignalR", "8.0.0" }, + { "Microsoft.AspNetCore.SignalR.Common", "8.0.0" }, + { "Microsoft.AspNetCore.SignalR.Core", "8.0.0" }, + { "Microsoft.AspNetCore.SignalR.Protocols.Json", "8.0.0" }, + { "Microsoft.AspNetCore.StaticFiles", "8.0.0" }, + { "Microsoft.AspNetCore.WebSockets", "8.0.0" }, + { "Microsoft.AspNetCore.WebUtilities", "8.0.0" }, + { "Microsoft.Extensions.Caching.Abstractions", "8.0.0" }, + { "Microsoft.Extensions.Caching.Memory", "8.0.0" }, + { "Microsoft.Extensions.Configuration", "8.0.0" }, + { "Microsoft.Extensions.Configuration.Abstractions", "8.0.0" }, + { "Microsoft.Extensions.Configuration.Binder", "8.0.0" }, + { "Microsoft.Extensions.Configuration.CommandLine", "8.0.0" }, + { "Microsoft.Extensions.Configuration.EnvironmentVariables", "8.0.0" }, + { "Microsoft.Extensions.Configuration.FileExtensions", "8.0.0" }, + { "Microsoft.Extensions.Configuration.Ini", "8.0.0" }, + { "Microsoft.Extensions.Configuration.Json", "8.0.0" }, + { "Microsoft.Extensions.Configuration.KeyPerFile", "8.0.0" }, + { "Microsoft.Extensions.Configuration.UserSecrets", "8.0.0" }, + { "Microsoft.Extensions.Configuration.Xml", "8.0.0" }, + { "Microsoft.Extensions.DependencyInjection", "8.0.0" }, + { "Microsoft.Extensions.DependencyInjection.Abstractions", "8.0.0" }, + { "Microsoft.Extensions.Diagnostics", "8.0.0" }, + { "Microsoft.Extensions.Diagnostics.Abstractions", "8.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks", "8.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "8.0.0" }, + { "Microsoft.Extensions.Features", "8.0.0" }, + { "Microsoft.Extensions.FileProviders.Abstractions", "8.0.0" }, + { "Microsoft.Extensions.FileProviders.Composite", "8.0.0" }, + { "Microsoft.Extensions.FileProviders.Embedded", "8.0.0" }, + { "Microsoft.Extensions.FileProviders.Physical", "8.0.0" }, + { "Microsoft.Extensions.FileSystemGlobbing", "8.0.0" }, + { "Microsoft.Extensions.Hosting", "8.0.0" }, + { "Microsoft.Extensions.Hosting.Abstractions", "8.0.0" }, + { "Microsoft.Extensions.Http", "8.0.0" }, + { "Microsoft.Extensions.Identity.Core", "8.0.0" }, + { "Microsoft.Extensions.Identity.Stores", "8.0.0" }, + { "Microsoft.Extensions.Localization", "8.0.0" }, + { "Microsoft.Extensions.Localization.Abstractions", "8.0.0" }, + { "Microsoft.Extensions.Logging", "8.0.0" }, + { "Microsoft.Extensions.Logging.Abstractions", "8.0.0" }, + { "Microsoft.Extensions.Logging.Configuration", "8.0.0" }, + { "Microsoft.Extensions.Logging.Console", "8.0.0" }, + { "Microsoft.Extensions.Logging.Debug", "8.0.0" }, + { "Microsoft.Extensions.Logging.EventLog", "8.0.0" }, + { "Microsoft.Extensions.Logging.EventSource", "8.0.0" }, + { "Microsoft.Extensions.Logging.TraceSource", "8.0.0" }, + { "Microsoft.Extensions.ObjectPool", "8.0.0" }, + { "Microsoft.Extensions.Options", "8.0.0" }, + { "Microsoft.Extensions.Options.ConfigurationExtensions", "8.0.0" }, + { "Microsoft.Extensions.Options.DataAnnotations", "8.0.0" }, + { "Microsoft.Extensions.Primitives", "8.0.0" }, + { "Microsoft.Extensions.WebEncoders", "8.0.0" }, + { "Microsoft.JSInterop", "8.0.0" }, + { "Microsoft.Net.Http.Headers", "8.0.0" }, + { "System.Diagnostics.EventLog", "8.0.0" }, + { "System.IO.Pipelines", "8.0.0" }, + { "System.Security.Cryptography.Pkcs", "8.0.0" }, + { "System.Security.Cryptography.Xml", "8.0.0" }, + { "System.Threading.RateLimiting", "8.0.0" }, + }; + + internal static FrameworkPackages WindowsDesktop { get; } = new(Net80, FrameworkNames.WindowsDesktopApp, NETCoreApp70.WindowsDesktop) + { + { "Microsoft.Win32.Registry.AccessControl", "8.0.0" }, + { "Microsoft.Win32.SystemEvents", "8.0.0" }, + { "System.CodeDom", "8.0.0" }, + { "System.Configuration.ConfigurationManager", "8.0.0" }, + { "System.Diagnostics.EventLog", "8.0.0" }, + { "System.Diagnostics.PerformanceCounter", "8.0.0" }, + { "System.Drawing.Common", "8.0.0" }, + { "System.IO.Packaging", "8.0.0" }, + { "System.Resources.Extensions", "8.0.0" }, + { "System.Security.Cryptography.Pkcs", "8.0.0" }, + { "System.Security.Cryptography.ProtectedData", "8.0.0" }, + { "System.Security.Cryptography.Xml", "8.0.0" }, + { "System.Security.Permissions", "8.0.0" }, + { "System.Threading.AccessControl", "8.0.0" }, + { "System.Windows.Extensions", "8.0.0" }, + }; + + internal static void Register() => FrameworkPackages.Register(Instance, AspNetCore, WindowsDesktop); + } +} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.net9.0.cs b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.net9.0.cs new file mode 100644 index 000000000000..a8e88a5526cc --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.net9.0.cs @@ -0,0 +1,196 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using System; +using global::NuGet.Frameworks; + +/// +/// Framework packages for net9.0. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp90 + { + private static NuGetFramework Net90 { get; } = new NuGetFramework(FrameworkConstants.FrameworkIdentifiers.NetCoreApp, new Version(9, 0)); + + internal static FrameworkPackages Instance { get; } = new(Net90, FrameworkNames.NetCoreApp, NETCoreApp80.Instance) + { + { "Microsoft.VisualBasic", "10.4.0" }, + { "System.Buffers", "5.0.0" }, + { "System.Collections.Immutable", "9.0.0" }, + { "System.Diagnostics.DiagnosticSource", "9.0.0" }, + { "System.Formats.Asn1", "9.0.0" }, + { "System.Formats.Tar", "9.0.0" }, + { "System.IO.Pipelines", "9.0.0" }, + { "System.Memory", "5.0.0" }, + { "System.Net.Http.Json", "9.0.0" }, + { "System.Numerics.Vectors", "5.0.0" }, + { "System.Private.Uri", "4.3.2" }, + { "System.Reflection.DispatchProxy", "6.0.0" }, + { "System.Reflection.Metadata", "9.0.0" }, + { "System.Runtime.CompilerServices.Unsafe", "7.0.0" }, + { "System.Text.Encoding.CodePages", "9.0.0" }, + { "System.Text.Encodings.Web", "9.0.0" }, + { "System.Text.Json", "9.0.0" }, + { "System.Threading.Channels", "9.0.0" }, + { "System.Threading.Tasks.Dataflow", "9.0.0" }, + { "System.Threading.Tasks.Extensions", "5.0.0" }, + { "System.Xml.XPath.XDocument", "5.0.0" }, + }; + + internal static FrameworkPackages AspNetCore { get; } = new(Net90, FrameworkNames.AspNetCoreApp, NETCoreApp80.AspNetCore) + { + { "Microsoft.AspNetCore", "9.0.0" }, + { "Microsoft.AspNetCore.Antiforgery", "9.0.0" }, + { "Microsoft.AspNetCore.Authentication", "9.0.0" }, + { "Microsoft.AspNetCore.Authentication.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.Authentication.BearerToken", "9.0.0" }, + { "Microsoft.AspNetCore.Authentication.Cookies", "9.0.0" }, + { "Microsoft.AspNetCore.Authentication.Core", "9.0.0" }, + { "Microsoft.AspNetCore.Authentication.OAuth", "9.0.0" }, + { "Microsoft.AspNetCore.Authorization", "9.0.0" }, + { "Microsoft.AspNetCore.Authorization.Policy", "9.0.0" }, + { "Microsoft.AspNetCore.Components", "9.0.0" }, + { "Microsoft.AspNetCore.Components.Authorization", "9.0.0" }, + { "Microsoft.AspNetCore.Components.Endpoints", "9.0.0" }, + { "Microsoft.AspNetCore.Components.Forms", "9.0.0" }, + { "Microsoft.AspNetCore.Components.Server", "9.0.0" }, + { "Microsoft.AspNetCore.Components.Web", "9.0.0" }, + { "Microsoft.AspNetCore.Connections.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.CookiePolicy", "9.0.0" }, + { "Microsoft.AspNetCore.Cors", "9.0.0" }, + { "Microsoft.AspNetCore.Cryptography.Internal", "9.0.0" }, + { "Microsoft.AspNetCore.Cryptography.KeyDerivation", "9.0.0" }, + { "Microsoft.AspNetCore.DataProtection", "9.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Extensions", "9.0.0" }, + { "Microsoft.AspNetCore.Diagnostics", "9.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.HealthChecks", "9.0.0" }, + { "Microsoft.AspNetCore.HostFiltering", "9.0.0" }, + { "Microsoft.AspNetCore.Hosting", "9.0.0" }, + { "Microsoft.AspNetCore.Hosting.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.Hosting.Server.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.Html.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.Http", "9.0.0" }, + { "Microsoft.AspNetCore.Http.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.Http.Connections", "9.0.0" }, + { "Microsoft.AspNetCore.Http.Connections.Common", "9.0.0" }, + { "Microsoft.AspNetCore.Http.Extensions", "9.0.0" }, + { "Microsoft.AspNetCore.Http.Features", "9.0.0" }, + { "Microsoft.AspNetCore.Http.Results", "9.0.0" }, + { "Microsoft.AspNetCore.HttpLogging", "9.0.0" }, + { "Microsoft.AspNetCore.HttpOverrides", "9.0.0" }, + { "Microsoft.AspNetCore.HttpsPolicy", "9.0.0" }, + { "Microsoft.AspNetCore.Identity", "9.0.0" }, + { "Microsoft.AspNetCore.Localization", "9.0.0" }, + { "Microsoft.AspNetCore.Localization.Routing", "9.0.0" }, + { "Microsoft.AspNetCore.Metadata", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.ApiExplorer", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.Core", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.Cors", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.DataAnnotations", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Json", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Xml", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.Localization", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.Razor", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.RazorPages", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.TagHelpers", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.ViewFeatures", "9.0.0" }, + { "Microsoft.AspNetCore.OutputCaching", "9.0.0" }, + { "Microsoft.AspNetCore.RateLimiting", "9.0.0" }, + { "Microsoft.AspNetCore.Razor", "9.0.0" }, + { "Microsoft.AspNetCore.Razor.Runtime", "9.0.0" }, + { "Microsoft.AspNetCore.RequestDecompression", "9.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching", "9.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.ResponseCompression", "9.0.0" }, + { "Microsoft.AspNetCore.Rewrite", "9.0.0" }, + { "Microsoft.AspNetCore.Routing", "9.0.0" }, + { "Microsoft.AspNetCore.Routing.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.Server.HttpSys", "9.0.0" }, + { "Microsoft.AspNetCore.Server.IIS", "9.0.0" }, + { "Microsoft.AspNetCore.Server.IISIntegration", "9.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel", "9.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Core", "9.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.NamedPipes", "9.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Quic", "9.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", "9.0.0" }, + { "Microsoft.AspNetCore.Session", "9.0.0" }, + { "Microsoft.AspNetCore.SignalR", "9.0.0" }, + { "Microsoft.AspNetCore.SignalR.Common", "9.0.0" }, + { "Microsoft.AspNetCore.SignalR.Core", "9.0.0" }, + { "Microsoft.AspNetCore.SignalR.Protocols.Json", "9.0.0" }, + { "Microsoft.AspNetCore.StaticAssets", "9.0.0" }, + { "Microsoft.AspNetCore.StaticFiles", "9.0.0" }, + { "Microsoft.AspNetCore.WebSockets", "9.0.0" }, + { "Microsoft.AspNetCore.WebUtilities", "9.0.0" }, + { "Microsoft.Extensions.Caching.Abstractions", "9.0.0" }, + { "Microsoft.Extensions.Caching.Memory", "9.0.0" }, + { "Microsoft.Extensions.Configuration", "9.0.0" }, + { "Microsoft.Extensions.Configuration.Abstractions", "9.0.0" }, + { "Microsoft.Extensions.Configuration.Binder", "9.0.0" }, + { "Microsoft.Extensions.Configuration.CommandLine", "9.0.0" }, + { "Microsoft.Extensions.Configuration.EnvironmentVariables", "9.0.0" }, + { "Microsoft.Extensions.Configuration.FileExtensions", "9.0.0" }, + { "Microsoft.Extensions.Configuration.Ini", "9.0.0" }, + { "Microsoft.Extensions.Configuration.Json", "9.0.0" }, + { "Microsoft.Extensions.Configuration.KeyPerFile", "9.0.0" }, + { "Microsoft.Extensions.Configuration.UserSecrets", "9.0.0" }, + { "Microsoft.Extensions.Configuration.Xml", "9.0.0" }, + { "Microsoft.Extensions.DependencyInjection", "9.0.0" }, + { "Microsoft.Extensions.DependencyInjection.Abstractions", "9.0.0" }, + { "Microsoft.Extensions.Diagnostics", "9.0.0" }, + { "Microsoft.Extensions.Diagnostics.Abstractions", "9.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks", "9.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "9.0.0" }, + { "Microsoft.Extensions.Features", "9.0.0" }, + { "Microsoft.Extensions.FileProviders.Abstractions", "9.0.0" }, + { "Microsoft.Extensions.FileProviders.Composite", "9.0.0" }, + { "Microsoft.Extensions.FileProviders.Embedded", "9.0.0" }, + { "Microsoft.Extensions.FileProviders.Physical", "9.0.0" }, + { "Microsoft.Extensions.FileSystemGlobbing", "9.0.0" }, + { "Microsoft.Extensions.Hosting", "9.0.0" }, + { "Microsoft.Extensions.Hosting.Abstractions", "9.0.0" }, + { "Microsoft.Extensions.Http", "9.0.0" }, + { "Microsoft.Extensions.Identity.Core", "9.0.0" }, + { "Microsoft.Extensions.Identity.Stores", "9.0.0" }, + { "Microsoft.Extensions.Localization", "9.0.0" }, + { "Microsoft.Extensions.Localization.Abstractions", "9.0.0" }, + { "Microsoft.Extensions.Logging", "9.0.0" }, + { "Microsoft.Extensions.Logging.Abstractions", "9.0.0" }, + { "Microsoft.Extensions.Logging.Configuration", "9.0.0" }, + { "Microsoft.Extensions.Logging.Console", "9.0.0" }, + { "Microsoft.Extensions.Logging.Debug", "9.0.0" }, + { "Microsoft.Extensions.Logging.EventLog", "9.0.0" }, + { "Microsoft.Extensions.Logging.EventSource", "9.0.0" }, + { "Microsoft.Extensions.Logging.TraceSource", "9.0.0" }, + { "Microsoft.Extensions.ObjectPool", "9.0.0" }, + { "Microsoft.Extensions.Options", "9.0.0" }, + { "Microsoft.Extensions.Options.ConfigurationExtensions", "9.0.0" }, + { "Microsoft.Extensions.Options.DataAnnotations", "9.0.0" }, + { "Microsoft.Extensions.Primitives", "9.0.0" }, + { "Microsoft.Extensions.WebEncoders", "9.0.0" }, + { "Microsoft.JSInterop", "9.0.0" }, + { "Microsoft.Net.Http.Headers", "9.0.0" }, + { "System.Diagnostics.EventLog", "9.0.0" }, + { "System.Security.Cryptography.Pkcs", "8.0.1" }, + { "System.Security.Cryptography.Xml", "9.0.0" }, + { "System.Threading.RateLimiting", "9.0.0" }, + }; + + internal static FrameworkPackages WindowsDesktop { get; } = new(Net90, FrameworkNames.WindowsDesktopApp, NETCoreApp80.WindowsDesktop) + { + { "System.Configuration.ConfigurationManager", "8.0.1" }, + { "System.Diagnostics.EventLog", "8.0.1" }, + { "System.Diagnostics.PerformanceCounter", "8.0.1" }, + { "System.Drawing.Common", "8.0.10" }, + { "System.IO.Packaging", "8.0.1" }, + { "System.Security.Cryptography.Pkcs", "8.0.1" }, + { "System.Security.Cryptography.Xml", "8.0.2" }, + }; + + internal static void Register() => FrameworkPackages.Register(Instance, AspNetCore, WindowsDesktop); + } +} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netcoreapp2.0.cs b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netcoreapp2.0.cs new file mode 100644 index 000000000000..69272e1ad888 --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netcoreapp2.0.cs @@ -0,0 +1,213 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; + +/// +/// Framework packages for .NETCoreApp,Version=v2.0. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp20 + { + internal static FrameworkPackages Instance { get; } = new(NetCoreApp20, FrameworkNames.NetCoreApp, NETStandard20.Instance) + { + { "Microsoft.CSharp", "4.4.0" }, + { "Microsoft.NETCore.App", "2.0.0" }, + { "Microsoft.VisualBasic", "10.2.0" }, + { "Microsoft.Win32.Registry", "4.4.0" }, + { "runtime.any.System.Collections", "4.3.0" }, + { "runtime.any.System.Diagnostics.Tools", "4.3.0" }, + { "runtime.any.System.Diagnostics.Tracing", "4.3.0" }, + { "runtime.any.System.Globalization", "4.3.0" }, + { "runtime.any.System.Globalization.Calendars", "4.3.0" }, + { "runtime.any.System.IO", "4.3.0" }, + { "runtime.any.System.Reflection", "4.3.0" }, + { "runtime.any.System.Reflection.Extensions", "4.3.0" }, + { "runtime.any.System.Reflection.Primitives", "4.3.0" }, + { "runtime.any.System.Resources.ResourceManager", "4.3.0" }, + { "runtime.any.System.Runtime", "4.3.1" }, + { "runtime.any.System.Runtime.Handles", "4.3.0" }, + { "runtime.any.System.Runtime.InteropServices", "4.3.0" }, + { "runtime.any.System.Text.Encoding", "4.3.0" }, + { "runtime.any.System.Text.Encoding.Extensions", "4.3.0" }, + { "runtime.any.System.Threading.Tasks", "4.3.0" }, + { "runtime.any.System.Threading.Timer", "4.3.0" }, + { "runtime.aot.System.Collections", "4.3.0" }, + { "runtime.aot.System.Diagnostics.Tools", "4.3.0" }, + { "runtime.aot.System.Diagnostics.Tracing", "4.3.0" }, + { "runtime.aot.System.Globalization", "4.3.0" }, + { "runtime.aot.System.Globalization.Calendars", "4.3.0" }, + { "runtime.aot.System.IO", "4.3.0" }, + { "runtime.aot.System.Reflection", "4.3.0" }, + { "runtime.aot.System.Reflection.Extensions", "4.3.0" }, + { "runtime.aot.System.Reflection.Primitives", "4.3.0" }, + { "runtime.aot.System.Resources.ResourceManager", "4.3.0" }, + { "runtime.aot.System.Runtime", "4.3.1" }, + { "runtime.aot.System.Runtime.Handles", "4.3.0" }, + { "runtime.aot.System.Runtime.InteropServices", "4.3.0" }, + { "runtime.aot.System.Text.Encoding", "4.3.0" }, + { "runtime.aot.System.Text.Encoding.Extensions", "4.3.0" }, + { "runtime.aot.System.Threading.Tasks", "4.3.0" }, + { "runtime.aot.System.Threading.Timer", "4.3.0" }, + { "runtime.debian.8-x64.runtime.native.System", "4.3.1" }, + { "runtime.debian.8-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.debian.8-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.debian.8-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.debian.8-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.debian.9-x64.runtime.native.System", "4.3.1" }, + { "runtime.debian.9-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.debian.9-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.debian.9-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.debian.9-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.debian.9-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.fedora.23-x64.runtime.native.System", "4.3.1" }, + { "runtime.fedora.23-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.fedora.23-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.fedora.23-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.fedora.24-x64.runtime.native.System", "4.3.1" }, + { "runtime.fedora.24-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.fedora.24-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.fedora.24-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.fedora.27-x64.runtime.native.System", "4.3.1" }, + { "runtime.fedora.27-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.fedora.27-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.fedora.27-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.fedora.27-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.fedora.27-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.fedora.28-x64.runtime.native.System", "4.3.1" }, + { "runtime.fedora.28-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.fedora.28-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.fedora.28-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.fedora.28-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.fedora.28-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.native.System.Security.Cryptography.Apple", "4.3.1" }, + { "runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.opensuse.13.2-x64.runtime.native.System", "4.3.1" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.opensuse.42.1-x64.runtime.native.System", "4.3.1" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.opensuse.42.3-x64.runtime.native.System", "4.3.1" }, + { "runtime.opensuse.42.3-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.opensuse.42.3-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.opensuse.42.3-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.opensuse.42.3-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.opensuse.42.3-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.osx.10.10-x64.runtime.native.System", "4.3.1" }, + { "runtime.osx.10.10-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.osx.10.10-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.osx.10.10-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple", "4.3.1" }, + { "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.rhel.7-x64.runtime.native.System", "4.3.1" }, + { "runtime.rhel.7-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.rhel.7-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.rhel.7-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System", "4.3.1" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System", "4.3.1" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System", "4.3.1" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.ubuntu.18.04-x64.runtime.native.System", "4.3.1" }, + { "runtime.ubuntu.18.04-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.ubuntu.18.04-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.ubuntu.18.04-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.ubuntu.18.04-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.ubuntu.18.04-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.unix.Microsoft.Win32.Primitives", "4.3.0" }, + { "runtime.unix.System.Console", "4.3.1" }, + { "runtime.unix.System.Diagnostics.Debug", "4.3.0" }, + { "runtime.unix.System.IO.FileSystem", "4.3.0" }, + { "runtime.unix.System.Net.Primitives", "4.3.0" }, + { "runtime.unix.System.Net.Sockets", "4.3.0" }, + { "runtime.unix.System.Private.Uri", "4.3.1" }, + { "runtime.unix.System.Runtime.Extensions", "4.3.1" }, + { "runtime.win.Microsoft.Win32.Primitives", "4.3.0" }, + { "runtime.win.System.Console", "4.3.1" }, + { "runtime.win.System.Diagnostics.Debug", "4.3.0" }, + { "runtime.win.System.IO.FileSystem", "4.3.0" }, + { "runtime.win.System.Net.Primitives", "4.3.0" }, + { "runtime.win.System.Net.Sockets", "4.3.0" }, + { "runtime.win.System.Runtime.Extensions", "4.3.1" }, + { "runtime.win10-arm-aot.runtime.native.System.IO.Compression", "4.0.1" }, + { "runtime.win10-arm64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.win10-x64-aot.runtime.native.System.IO.Compression", "4.0.1" }, + { "runtime.win10-x86-aot.runtime.native.System.IO.Compression", "4.0.1" }, + { "runtime.win7-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.win7-x86.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.win7.System.Private.Uri", "4.3.1" }, + { "runtime.win8-arm.runtime.native.System.IO.Compression", "4.3.2" }, + { "System.Buffers", "4.4.0" }, + { "System.Collections.Concurrent", "4.3.0" }, + { "System.Collections.Immutable", "1.4.0" }, + { "System.ComponentModel", "4.3.0" }, + { "System.ComponentModel.Annotations", "4.4.0" }, + { "System.ComponentModel.EventBasedAsync", "4.3.0" }, + { "System.Diagnostics.Contracts", "4.3.0" }, + { "System.Diagnostics.DiagnosticSource", "4.4.1" }, + { "System.Dynamic.Runtime", "4.3.0" }, + { "System.IO.FileSystem.AccessControl", "4.4.0" }, + { "System.Linq.Parallel", "4.3.0" }, + { "System.Linq.Queryable", "4.3.0" }, + { "System.Net.Requests", "4.3.0" }, + { "System.Net.WebHeaderCollection", "4.3.0" }, + { "System.Numerics.Vectors", "4.4.0" }, + { "System.ObjectModel", "4.3.0" }, + { "System.Private.DataContractSerialization", "4.3.0" }, + { "System.Private.Uri", "4.3.0" }, + { "System.Reflection.DispatchProxy", "4.4.0" }, + { "System.Reflection.Emit", "4.7.0" }, + { "System.Reflection.Emit.ILGeneration", "4.7.0" }, + { "System.Reflection.Emit.Lightweight", "4.7.0" }, + { "System.Reflection.Metadata", "1.5.0" }, + { "System.Reflection.TypeExtensions", "4.7.0" }, + { "System.Runtime.InteropServices.WindowsRuntime", "4.3.0" }, + { "System.Runtime.Loader", "4.3.0" }, + { "System.Runtime.Numerics", "4.3.0" }, + { "System.Runtime.Serialization.Json", "4.3.0" }, + { "System.Security.AccessControl", "4.4.0" }, + { "System.Security.Cryptography.Cng", "4.4.0" }, + { "System.Security.Cryptography.OpenSsl", "4.4.0" }, + { "System.Security.Principal", "4.3.0" }, + { "System.Security.Principal.Windows", "4.4.0" }, + { "System.Text.RegularExpressions", "4.3.1" }, + { "System.Threading", "4.3.0" }, + { "System.Threading.Tasks.Dataflow", "4.8.0" }, + { "System.Threading.Tasks.Extensions", "4.4.0" }, + { "System.Threading.Tasks.Parallel", "4.3.0" }, + { "System.Xml.XDocument", "4.3.0" }, + { "System.Xml.XmlSerializer", "4.3.0" }, + }; + + internal static void Register() => FrameworkPackages.Register(Instance); + } +} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netcoreapp2.1.cs b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netcoreapp2.1.cs new file mode 100644 index 000000000000..a046281fb09e --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netcoreapp2.1.cs @@ -0,0 +1,39 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; + +/// +/// Framework packages for .NETCoreApp,Version=v2.1. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp21 + { + internal static FrameworkPackages Instance { get; } = new(NetCoreApp21, FrameworkNames.NetCoreApp, NETCoreApp20.Instance) + { + { "Microsoft.CSharp", "4.5.0" }, + { "Microsoft.NETCore.App", "2.1.0" }, + { "Microsoft.VisualBasic", "10.3.0" }, + { "Microsoft.Win32.Registry", "4.5.0" }, + { "System.Buffers", "4.5.0" }, + { "System.Collections.Immutable", "1.5.0" }, + { "System.ComponentModel.Annotations", "4.5.0" }, + { "System.Diagnostics.DiagnosticSource", "4.5.0" }, + { "System.IO.FileSystem.AccessControl", "4.5.0" }, + { "System.IO.Pipes.AccessControl", "4.5.0" }, + { "System.Memory", "4.5.5" }, + { "System.Numerics.Vectors", "4.5.0" }, + { "System.Reflection.DispatchProxy", "4.5.0" }, + { "System.Reflection.Metadata", "1.6.0" }, + { "System.Security.AccessControl", "4.5.0" }, + { "System.Security.Cryptography.Cng", "4.5.2" }, + { "System.Security.Cryptography.OpenSsl", "4.5.0" }, + { "System.Security.Principal.Windows", "4.5.0" }, + { "System.Threading.Tasks.Dataflow", "4.9.0" }, + { "System.Threading.Tasks.Extensions", "4.5.4" }, + { "System.ValueTuple", "4.5.0" }, + }; + + internal static void Register() => FrameworkPackages.Register(Instance); + } +} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netcoreapp2.2.cs b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netcoreapp2.2.cs new file mode 100644 index 000000000000..a3a28741fe16 --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netcoreapp2.2.cs @@ -0,0 +1,17 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; + +/// +/// Framework packages for .NETCoreApp,Version=v2.2. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp22 + { + // .NETCore 2.2 was the same as .NETCore 2.1 + internal static FrameworkPackages Instance { get; } = new(NetCoreApp22, FrameworkNames.NetCoreApp, NETCoreApp21.Instance); + + internal static void Register() => FrameworkPackages.Register(Instance); + } +} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netcoreapp3.0.cs b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netcoreapp3.0.cs new file mode 100644 index 000000000000..079a9a0cd678 --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netcoreapp3.0.cs @@ -0,0 +1,197 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; + +/// +/// Framework packages for .NETCoreApp,Version=v3.0. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp30 + { + internal static FrameworkPackages Instance { get; } = new(NetCoreApp30, FrameworkNames.NetCoreApp, NETCoreApp21.Instance) + { + { "Microsoft.CSharp", "4.6.0" }, + { "Microsoft.Win32.Registry", "4.6.0" }, + { "System.Buffers", "4.5.1" }, + { "System.Collections.Immutable", "1.6.0" }, + { "System.ComponentModel.Annotations", "4.6.0" }, + { "System.Data.DataSetExtensions", "4.5.0" }, + { "System.Diagnostics.DiagnosticSource", "4.6.0" }, + { "System.IO.FileSystem.AccessControl", "4.6.0" }, + { "System.IO.Pipes.AccessControl", "4.6.0" }, + { "System.Reflection.DispatchProxy", "4.6.0" }, + { "System.Reflection.Metadata", "1.7.0" }, + { "System.Runtime.CompilerServices.Unsafe", "4.6.0" }, + { "System.Runtime.WindowsRuntime", "4.6.0" }, + { "System.Runtime.WindowsRuntime.UI.Xaml", "4.6.0" }, + { "System.Security.AccessControl", "4.6.0" }, + { "System.Security.Cryptography.Cng", "4.6.0" }, + { "System.Security.Cryptography.OpenSsl", "4.6.0" }, + { "System.Security.Cryptography.Xml", "4.4.0" }, + { "System.Security.Principal.Windows", "4.6.0" }, + { "System.Text.Encoding.CodePages", "4.6.0" }, + { "System.Text.Encodings.Web", "4.6.0" }, + { "System.Text.Json", "4.6.0" }, + { "System.Threading.Channels", "4.6.0" }, + { "System.Threading.Tasks.Dataflow", "4.10.0" }, + }; + + internal static FrameworkPackages AspNetCore { get; } = new(NetCoreApp30, FrameworkNames.AspNetCoreApp) + { + { "Microsoft.AspNetCore", "3.0.0" }, + { "Microsoft.AspNetCore.Antiforgery", "3.0.0" }, + { "Microsoft.AspNetCore.Authentication", "3.0.0" }, + { "Microsoft.AspNetCore.Authentication.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.Authentication.Cookies", "3.0.0" }, + { "Microsoft.AspNetCore.Authentication.Core", "3.0.0" }, + { "Microsoft.AspNetCore.Authentication.OAuth", "3.0.0" }, + { "Microsoft.AspNetCore.Authorization", "3.0.0" }, + { "Microsoft.AspNetCore.Authorization.Policy", "3.0.0" }, + { "Microsoft.AspNetCore.Components", "3.0.0" }, + { "Microsoft.AspNetCore.Components.Authorization", "3.0.0" }, + { "Microsoft.AspNetCore.Components.Forms", "3.0.0" }, + { "Microsoft.AspNetCore.Components.Server", "3.0.0" }, + { "Microsoft.AspNetCore.Components.Web", "3.0.0" }, + { "Microsoft.AspNetCore.Connections.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.CookiePolicy", "3.0.0" }, + { "Microsoft.AspNetCore.Cors", "3.0.0" }, + { "Microsoft.AspNetCore.Cryptography.Internal", "3.0.0" }, + { "Microsoft.AspNetCore.Cryptography.KeyDerivation", "3.0.0" }, + { "Microsoft.AspNetCore.DataProtection", "3.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Extensions", "3.0.0" }, + { "Microsoft.AspNetCore.Diagnostics", "3.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.HealthChecks", "3.0.0" }, + { "Microsoft.AspNetCore.HostFiltering", "3.0.0" }, + { "Microsoft.AspNetCore.Hosting", "3.0.0" }, + { "Microsoft.AspNetCore.Hosting.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.Hosting.Server.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.Html.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.Http", "3.0.0" }, + { "Microsoft.AspNetCore.Http.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.Http.Connections", "3.0.0" }, + { "Microsoft.AspNetCore.Http.Connections.Common", "3.0.0" }, + { "Microsoft.AspNetCore.Http.Extensions", "3.0.0" }, + { "Microsoft.AspNetCore.Http.Features", "3.0.0" }, + { "Microsoft.AspNetCore.HttpOverrides", "3.0.0" }, + { "Microsoft.AspNetCore.HttpsPolicy", "3.0.0" }, + { "Microsoft.AspNetCore.Identity", "3.0.0" }, + { "Microsoft.AspNetCore.Localization", "3.0.0" }, + { "Microsoft.AspNetCore.Localization.Routing", "3.0.0" }, + { "Microsoft.AspNetCore.Metadata", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.ApiExplorer", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.Core", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.Cors", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.DataAnnotations", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Json", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Xml", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.Localization", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.Razor", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.RazorPages", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.TagHelpers", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.ViewFeatures", "3.0.0" }, + { "Microsoft.AspNetCore.Razor", "3.0.0" }, + { "Microsoft.AspNetCore.Razor.Runtime", "3.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching", "3.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.ResponseCompression", "3.0.0" }, + { "Microsoft.AspNetCore.Rewrite", "3.0.0" }, + { "Microsoft.AspNetCore.Routing", "3.0.0" }, + { "Microsoft.AspNetCore.Routing.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.Server.HttpSys", "3.0.0" }, + { "Microsoft.AspNetCore.Server.IIS", "3.0.0" }, + { "Microsoft.AspNetCore.Server.IISIntegration", "3.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel", "3.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Core", "3.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", "3.0.0" }, + { "Microsoft.AspNetCore.Session", "3.0.0" }, + { "Microsoft.AspNetCore.SignalR", "3.0.0" }, + { "Microsoft.AspNetCore.SignalR.Common", "3.0.0" }, + { "Microsoft.AspNetCore.SignalR.Core", "3.0.0" }, + { "Microsoft.AspNetCore.SignalR.Protocols.Json", "3.0.0" }, + { "Microsoft.AspNetCore.StaticFiles", "3.0.0" }, + { "Microsoft.AspNetCore.WebSockets", "3.0.0" }, + { "Microsoft.AspNetCore.WebUtilities", "3.0.0" }, + { "Microsoft.Extensions.Caching.Abstractions", "3.0.0" }, + { "Microsoft.Extensions.Caching.Memory", "3.0.0" }, + { "Microsoft.Extensions.Configuration", "3.0.0" }, + { "Microsoft.Extensions.Configuration.Abstractions", "3.0.0" }, + { "Microsoft.Extensions.Configuration.Binder", "3.0.0" }, + { "Microsoft.Extensions.Configuration.CommandLine", "3.0.0" }, + { "Microsoft.Extensions.Configuration.EnvironmentVariables", "3.0.0" }, + { "Microsoft.Extensions.Configuration.FileExtensions", "3.0.0" }, + { "Microsoft.Extensions.Configuration.Ini", "3.0.0" }, + { "Microsoft.Extensions.Configuration.Json", "3.0.0" }, + { "Microsoft.Extensions.Configuration.KeyPerFile", "3.0.0" }, + { "Microsoft.Extensions.Configuration.UserSecrets", "3.0.0" }, + { "Microsoft.Extensions.Configuration.Xml", "3.0.0" }, + { "Microsoft.Extensions.DependencyInjection", "3.0.0" }, + { "Microsoft.Extensions.DependencyInjection.Abstractions", "3.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks", "3.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "3.0.0" }, + { "Microsoft.Extensions.FileProviders.Abstractions", "3.0.0" }, + { "Microsoft.Extensions.FileProviders.Composite", "3.0.0" }, + { "Microsoft.Extensions.FileProviders.Embedded", "3.0.0" }, + { "Microsoft.Extensions.FileProviders.Physical", "3.0.0" }, + { "Microsoft.Extensions.FileSystemGlobbing", "3.0.0" }, + { "Microsoft.Extensions.Hosting", "3.0.0" }, + { "Microsoft.Extensions.Hosting.Abstractions", "3.0.0" }, + { "Microsoft.Extensions.Http", "3.0.0" }, + { "Microsoft.Extensions.Identity.Core", "3.0.0" }, + { "Microsoft.Extensions.Identity.Stores", "3.0.0" }, + { "Microsoft.Extensions.Localization", "3.0.0" }, + { "Microsoft.Extensions.Localization.Abstractions", "3.0.0" }, + { "Microsoft.Extensions.Logging", "3.0.0" }, + { "Microsoft.Extensions.Logging.Abstractions", "3.0.0" }, + { "Microsoft.Extensions.Logging.Configuration", "3.0.0" }, + { "Microsoft.Extensions.Logging.Console", "3.0.0" }, + { "Microsoft.Extensions.Logging.Debug", "3.0.0" }, + { "Microsoft.Extensions.Logging.EventLog", "3.0.0" }, + { "Microsoft.Extensions.Logging.EventSource", "3.0.0" }, + { "Microsoft.Extensions.Logging.TraceSource", "3.0.0" }, + { "Microsoft.Extensions.ObjectPool", "3.0.0" }, + { "Microsoft.Extensions.Options", "3.0.0" }, + { "Microsoft.Extensions.Options.ConfigurationExtensions", "3.0.0" }, + { "Microsoft.Extensions.Options.DataAnnotations", "3.0.0" }, + { "Microsoft.Extensions.Primitives", "3.0.0" }, + { "Microsoft.Extensions.WebEncoders", "3.0.0" }, + { "Microsoft.JSInterop", "3.0.0" }, + { "Microsoft.Net.Http.Headers", "3.0.0" }, + { "Microsoft.Win32.Registry", "4.6.0" }, + { "System.Diagnostics.EventLog", "4.6.0" }, + { "System.IO.Pipelines", "4.6.0" }, + { "System.Security.AccessControl", "4.6.0" }, + { "System.Security.Cryptography.Cng", "4.6.0" }, + { "System.Security.Cryptography.Xml", "4.6.0" }, + { "System.Security.Permissions", "4.6.0" }, + { "System.Security.Principal.Windows", "4.6.0" }, + { "System.Windows.Extensions", "4.6.0" }, + }; + + internal static FrameworkPackages WindowsDesktop { get; } = new(NetCoreApp30, FrameworkNames.WindowsDesktopApp) + { + { "Microsoft.Win32.Registry.AccessControl", "4.6.0" }, + { "Microsoft.Win32.SystemEvents", "4.6.0" }, + { "System.CodeDom", "4.6.0" }, + { "System.Configuration.ConfigurationManager", "4.6.0" }, + { "System.Diagnostics.EventLog", "4.6.0" }, + { "System.Diagnostics.PerformanceCounter", "4.5.0" }, + { "System.DirectoryServices", "4.6.0" }, + { "System.Drawing.Common", "4.7.3" }, + { "System.IO.Packaging", "4.6.0" }, + { "System.Resources.Extensions", "4.6.0" }, + { "System.Security.Cryptography.Pkcs", "4.6.0" }, + { "System.Security.Cryptography.ProtectedData", "4.6.0" }, + { "System.Security.Cryptography.Xml", "4.6.0" }, + { "System.Security.Permissions", "4.6.0" }, + { "System.Threading.AccessControl", "4.6.0" }, + { "System.Windows.Extensions", "4.6.0" }, + }; + + internal static void Register() => FrameworkPackages.Register(Instance, AspNetCore, WindowsDesktop); + } +} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netcoreapp3.1.cs b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netcoreapp3.1.cs new file mode 100644 index 000000000000..ce3338d80a5b --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netcoreapp3.1.cs @@ -0,0 +1,194 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; + +/// +/// Framework packages for .NETCoreApp,Version=v3.1. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp31 + { + internal static FrameworkPackages Instance { get; } = new(NetCoreApp31, FrameworkNames.NetCoreApp, NETCoreApp30.Instance) + { + { "Microsoft.CSharp", "4.7.0" }, + { "Microsoft.Win32.Registry", "4.7.0" }, + { "System.Collections.Immutable", "1.7.0" }, + { "System.ComponentModel.Annotations", "4.7.0" }, + { "System.Diagnostics.DiagnosticSource", "4.7.0" }, + { "System.IO.FileSystem.AccessControl", "4.7.0" }, + { "System.Reflection.DispatchProxy", "4.7.0" }, + { "System.Reflection.Metadata", "1.8.0" }, + { "System.Runtime.CompilerServices.Unsafe", "4.7.1" }, + { "System.Runtime.WindowsRuntime", "4.7.0" }, + { "System.Runtime.WindowsRuntime.UI.Xaml", "4.7.0" }, + { "System.Security.AccessControl", "4.7.0" }, + { "System.Security.Cryptography.OpenSsl", "4.7.0" }, + { "System.Security.Principal.Windows", "4.7.0" }, + { "System.Text.Encoding.CodePages", "4.7.0" }, + { "System.Text.Encodings.Web", "4.7.0" }, + { "System.Text.Json", "4.7.0" }, + { "System.Threading.Channels", "4.7.0" }, + { "System.Threading.Tasks.Dataflow", "4.11.0" }, + }; + + internal static FrameworkPackages AspNetCore { get; } = new(NetCoreApp31, FrameworkNames.AspNetCoreApp, NETCoreApp30.AspNetCore) + { + { "Microsoft.AspNetCore", "3.1.0" }, + { "Microsoft.AspNetCore.Antiforgery", "3.1.0" }, + { "Microsoft.AspNetCore.Authentication", "3.1.0" }, + { "Microsoft.AspNetCore.Authentication.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.Authentication.Cookies", "3.1.0" }, + { "Microsoft.AspNetCore.Authentication.Core", "3.1.0" }, + { "Microsoft.AspNetCore.Authentication.OAuth", "3.1.0" }, + { "Microsoft.AspNetCore.Authorization", "3.1.0" }, + { "Microsoft.AspNetCore.Authorization.Policy", "3.1.0" }, + { "Microsoft.AspNetCore.Components", "3.1.0" }, + { "Microsoft.AspNetCore.Components.Authorization", "3.1.0" }, + { "Microsoft.AspNetCore.Components.Forms", "3.1.0" }, + { "Microsoft.AspNetCore.Components.Server", "3.1.0" }, + { "Microsoft.AspNetCore.Components.Web", "3.1.0" }, + { "Microsoft.AspNetCore.Connections.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.CookiePolicy", "3.1.0" }, + { "Microsoft.AspNetCore.Cors", "3.1.0" }, + { "Microsoft.AspNetCore.Cryptography.Internal", "3.1.0" }, + { "Microsoft.AspNetCore.Cryptography.KeyDerivation", "3.1.0" }, + { "Microsoft.AspNetCore.DataProtection", "3.1.0" }, + { "Microsoft.AspNetCore.DataProtection.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.DataProtection.Extensions", "3.1.0" }, + { "Microsoft.AspNetCore.Diagnostics", "3.1.0" }, + { "Microsoft.AspNetCore.Diagnostics.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.Diagnostics.HealthChecks", "3.1.0" }, + { "Microsoft.AspNetCore.HostFiltering", "3.1.0" }, + { "Microsoft.AspNetCore.Hosting", "3.1.0" }, + { "Microsoft.AspNetCore.Hosting.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.Hosting.Server.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.Html.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.Http", "3.1.0" }, + { "Microsoft.AspNetCore.Http.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.Http.Connections", "3.1.0" }, + { "Microsoft.AspNetCore.Http.Connections.Common", "3.1.0" }, + { "Microsoft.AspNetCore.Http.Extensions", "3.1.0" }, + { "Microsoft.AspNetCore.Http.Features", "3.1.0" }, + { "Microsoft.AspNetCore.HttpOverrides", "3.1.0" }, + { "Microsoft.AspNetCore.HttpsPolicy", "3.1.0" }, + { "Microsoft.AspNetCore.Identity", "3.1.0" }, + { "Microsoft.AspNetCore.Localization", "3.1.0" }, + { "Microsoft.AspNetCore.Localization.Routing", "3.1.0" }, + { "Microsoft.AspNetCore.Metadata", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.ApiExplorer", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.Core", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.Cors", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.DataAnnotations", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Json", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Xml", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.Localization", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.Razor", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.RazorPages", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.TagHelpers", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.ViewFeatures", "3.1.0" }, + { "Microsoft.AspNetCore.Razor", "3.1.0" }, + { "Microsoft.AspNetCore.Razor.Runtime", "3.1.0" }, + { "Microsoft.AspNetCore.ResponseCaching", "3.1.0" }, + { "Microsoft.AspNetCore.ResponseCaching.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.ResponseCompression", "3.1.0" }, + { "Microsoft.AspNetCore.Rewrite", "3.1.0" }, + { "Microsoft.AspNetCore.Routing", "3.1.0" }, + { "Microsoft.AspNetCore.Routing.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.Server.HttpSys", "3.1.0" }, + { "Microsoft.AspNetCore.Server.IIS", "3.1.0" }, + { "Microsoft.AspNetCore.Server.IISIntegration", "3.1.0" }, + { "Microsoft.AspNetCore.Server.Kestrel", "3.1.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Core", "3.1.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", "3.1.0" }, + { "Microsoft.AspNetCore.Session", "3.1.0" }, + { "Microsoft.AspNetCore.SignalR", "3.1.0" }, + { "Microsoft.AspNetCore.SignalR.Common", "3.1.0" }, + { "Microsoft.AspNetCore.SignalR.Core", "3.1.0" }, + { "Microsoft.AspNetCore.SignalR.Protocols.Json", "3.1.0" }, + { "Microsoft.AspNetCore.StaticFiles", "3.1.0" }, + { "Microsoft.AspNetCore.WebSockets", "3.1.0" }, + { "Microsoft.AspNetCore.WebUtilities", "3.1.0" }, + { "Microsoft.Extensions.Caching.Abstractions", "3.1.0" }, + { "Microsoft.Extensions.Caching.Memory", "3.1.0" }, + { "Microsoft.Extensions.Configuration", "3.1.0" }, + { "Microsoft.Extensions.Configuration.Abstractions", "3.1.0" }, + { "Microsoft.Extensions.Configuration.Binder", "3.1.0" }, + { "Microsoft.Extensions.Configuration.CommandLine", "3.1.0" }, + { "Microsoft.Extensions.Configuration.EnvironmentVariables", "3.1.0" }, + { "Microsoft.Extensions.Configuration.FileExtensions", "3.1.0" }, + { "Microsoft.Extensions.Configuration.Ini", "3.1.0" }, + { "Microsoft.Extensions.Configuration.Json", "3.1.0" }, + { "Microsoft.Extensions.Configuration.KeyPerFile", "3.1.0" }, + { "Microsoft.Extensions.Configuration.UserSecrets", "3.1.0" }, + { "Microsoft.Extensions.Configuration.Xml", "3.1.0" }, + { "Microsoft.Extensions.DependencyInjection", "3.1.0" }, + { "Microsoft.Extensions.DependencyInjection.Abstractions", "3.1.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks", "3.1.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "3.1.0" }, + { "Microsoft.Extensions.FileProviders.Abstractions", "3.1.0" }, + { "Microsoft.Extensions.FileProviders.Composite", "3.1.0" }, + { "Microsoft.Extensions.FileProviders.Embedded", "3.1.0" }, + { "Microsoft.Extensions.FileProviders.Physical", "3.1.0" }, + { "Microsoft.Extensions.FileSystemGlobbing", "3.1.0" }, + { "Microsoft.Extensions.Hosting", "3.1.0" }, + { "Microsoft.Extensions.Hosting.Abstractions", "3.1.0" }, + { "Microsoft.Extensions.Http", "3.1.0" }, + { "Microsoft.Extensions.Identity.Core", "3.1.0" }, + { "Microsoft.Extensions.Identity.Stores", "3.1.0" }, + { "Microsoft.Extensions.Localization", "3.1.0" }, + { "Microsoft.Extensions.Localization.Abstractions", "3.1.0" }, + { "Microsoft.Extensions.Logging", "3.1.0" }, + { "Microsoft.Extensions.Logging.Abstractions", "3.1.0" }, + { "Microsoft.Extensions.Logging.Configuration", "3.1.0" }, + { "Microsoft.Extensions.Logging.Console", "3.1.0" }, + { "Microsoft.Extensions.Logging.Debug", "3.1.0" }, + { "Microsoft.Extensions.Logging.EventLog", "3.1.0" }, + { "Microsoft.Extensions.Logging.EventSource", "3.1.0" }, + { "Microsoft.Extensions.Logging.TraceSource", "3.1.0" }, + { "Microsoft.Extensions.ObjectPool", "3.1.0" }, + { "Microsoft.Extensions.Options", "3.1.0" }, + { "Microsoft.Extensions.Options.ConfigurationExtensions", "3.1.0" }, + { "Microsoft.Extensions.Options.DataAnnotations", "3.1.0" }, + { "Microsoft.Extensions.Primitives", "3.1.0" }, + { "Microsoft.Extensions.WebEncoders", "3.1.0" }, + { "Microsoft.JSInterop", "3.1.0" }, + { "Microsoft.Net.Http.Headers", "3.1.0" }, + { "Microsoft.Win32.Registry", "4.7.0" }, + { "Microsoft.Win32.SystemEvents", "4.7.0" }, + { "System.Diagnostics.EventLog", "4.7.0" }, + { "System.Drawing.Common", "4.7.3" }, + { "System.IO.Pipelines", "4.7.0" }, + { "System.Security.AccessControl", "4.7.0" }, + { "System.Security.Cryptography.Cng", "4.7.0" }, + { "System.Security.Cryptography.Pkcs", "4.7.0" }, + { "System.Security.Cryptography.Xml", "4.7.0" }, + { "System.Security.Permissions", "4.7.0" }, + { "System.Security.Principal.Windows", "4.7.0" }, + { "System.Windows.Extensions", "4.7.0" }, + }; + + internal static FrameworkPackages WindowsDesktop { get; } = new(NetCoreApp31, FrameworkNames.WindowsDesktopApp, NETCoreApp30.WindowsDesktop) + { + { "Microsoft.Win32.Registry.AccessControl", "4.7.0" }, + { "Microsoft.Win32.SystemEvents", "4.7.0" }, + { "System.CodeDom", "4.7.0" }, + { "System.Configuration.ConfigurationManager", "4.7.0" }, + { "System.Diagnostics.EventLog", "4.7.0" }, + { "System.Diagnostics.PerformanceCounter", "4.7.0" }, + { "System.DirectoryServices", "8.0.0" }, + { "System.IO.Packaging", "4.7.0" }, + { "System.Resources.Extensions", "4.7.0" }, + { "System.Security.Cryptography.Pkcs", "4.7.0" }, + { "System.Security.Cryptography.ProtectedData", "4.7.0" }, + { "System.Security.Cryptography.Xml", "4.7.0" }, + { "System.Security.Permissions", "4.7.0" }, + { "System.Threading.AccessControl", "4.7.0" }, + { "System.Windows.Extensions", "4.7.0" }, + }; + + internal static void Register() => FrameworkPackages.Register(Instance, AspNetCore, WindowsDesktop); + } +} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netstandard2.0.cs b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netstandard2.0.cs new file mode 100644 index 000000000000..66c9bdd64cdf --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netstandard2.0.cs @@ -0,0 +1,110 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; + +/// +/// Framework packages for .NETStandard,Version=v2.0. +/// +internal partial class FrameworkPackages +{ + internal static class NETStandard20 + { + internal static FrameworkPackages Instance { get; } = new(NetStandard20, FrameworkNames.NetStandardLibrary) + { + { "Microsoft.Win32.Primitives", "4.3.0" }, + { "System.AppContext", "4.3.0" }, + { "System.Collections", "4.3.0" }, + { "System.Collections.NonGeneric", "4.3.0" }, + { "System.Collections.Specialized", "4.3.0" }, + { "System.ComponentModel", "4.0.1" }, + { "System.ComponentModel.EventBasedAsync", "4.0.11" }, + { "System.ComponentModel.Primitives", "4.3.0" }, + { "System.ComponentModel.TypeConverter", "4.3.0" }, + { "System.Console", "4.3.1" }, + { "System.Data.Common", "4.3.0" }, + { "System.Diagnostics.Contracts", "4.0.1" }, + { "System.Diagnostics.Debug", "4.3.0" }, + { "System.Diagnostics.FileVersionInfo", "4.3.0" }, + { "System.Diagnostics.Process", "4.3.0" }, + { "System.Diagnostics.StackTrace", "4.3.0" }, + { "System.Diagnostics.TextWriterTraceListener", "4.3.0" }, + { "System.Diagnostics.Tools", "4.3.0" }, + { "System.Diagnostics.TraceSource", "4.3.0" }, + { "System.Diagnostics.Tracing", "4.3.0" }, + { "System.Drawing.Primitives", "4.3.0" }, + { "System.Dynamic.Runtime", "4.0.11" }, + { "System.Globalization", "4.3.0" }, + { "System.Globalization.Calendars", "4.3.0" }, + { "System.Globalization.Extensions", "4.3.0" }, + { "System.IO", "4.3.0" }, + { "System.IO.Compression", "4.3.0" }, + { "System.IO.Compression.ZipFile", "4.3.0" }, + { "System.IO.FileSystem", "4.3.0" }, + { "System.IO.FileSystem.DriveInfo", "4.3.1" }, + { "System.IO.FileSystem.Primitives", "4.3.0" }, + { "System.IO.FileSystem.Watcher", "4.3.0" }, + { "System.IO.IsolatedStorage", "4.3.0" }, + { "System.IO.MemoryMappedFiles", "4.3.0" }, + { "System.IO.Pipes", "4.3.0" }, + { "System.IO.UnmanagedMemoryStream", "4.3.0" }, + { "System.Linq", "4.3.0" }, + { "System.Linq.Expressions", "4.3.0" }, + { "System.Linq.Parallel", "4.0.1" }, + { "System.Linq.Queryable", "4.0.1" }, + { "System.Net.Http", "4.3.4" }, + { "System.Net.NameResolution", "4.3.0" }, + { "System.Net.NetworkInformation", "4.3.0" }, + { "System.Net.Ping", "4.3.0" }, + { "System.Net.Primitives", "4.3.1" }, + { "System.Net.Requests", "4.0.11" }, + { "System.Net.Security", "4.3.2" }, + { "System.Net.Sockets", "4.3.0" }, + { "System.Net.WebHeaderCollection", "4.0.1" }, + { "System.Net.WebSockets", "4.3.0" }, + { "System.Net.WebSockets.Client", "4.3.2" }, + { "System.Reflection", "4.3.0" }, + { "System.Reflection.Extensions", "4.3.0" }, + { "System.Reflection.Primitives", "4.3.0" }, + { "System.Resources.Reader", "4.3.0" }, + { "System.Resources.ResourceManager", "4.3.0" }, + { "System.Resources.Writer", "4.3.0" }, + { "System.Runtime", "4.3.1" }, + { "System.Runtime.CompilerServices.VisualC", "4.3.0" }, + { "System.Runtime.Extensions", "4.3.1" }, + { "System.Runtime.Handles", "4.3.0" }, + { "System.Runtime.InteropServices", "4.3.0" }, + { "System.Runtime.InteropServices.RuntimeInformation", "4.3.0" }, + { "System.Runtime.Numerics", "4.0.1" }, + { "System.Runtime.Serialization.Formatters", "4.3.0" }, + { "System.Runtime.Serialization.Primitives", "4.3.0" }, + { "System.Runtime.Serialization.Xml", "4.3.0" }, + { "System.Security.Claims", "4.3.0" }, + { "System.Security.Cryptography.Algorithms", "4.3.1" }, + { "System.Security.Cryptography.Csp", "4.3.0" }, + { "System.Security.Cryptography.Encoding", "4.3.0" }, + { "System.Security.Cryptography.Primitives", "4.3.0" }, + { "System.Security.Cryptography.X509Certificates", "4.3.2" }, + { "System.Security.Principal", "4.0.1" }, + { "System.Security.SecureString", "4.3.0" }, + { "System.Text.Encoding", "4.3.0" }, + { "System.Text.Encoding.Extensions", "4.3.0" }, + { "System.Text.RegularExpressions", "4.3.0" }, + { "System.Threading", "4.0.11" }, + { "System.Threading.Overlapped", "4.3.0" }, + { "System.Threading.Tasks", "4.3.0" }, + { "System.Threading.Tasks.Parallel", "4.0.1" }, + { "System.Threading.Thread", "4.3.0" }, + { "System.Threading.ThreadPool", "4.3.0" }, + { "System.Threading.Timer", "4.3.0" }, + { "System.ValueTuple", "4.4.0" }, + { "System.Xml.ReaderWriter", "4.3.1" }, + { "System.Xml.XDocument", "4.0.11" }, + { "System.Xml.XmlDocument", "4.3.0" }, + { "System.Xml.XmlSerializer", "4.0.11" }, + { "System.Xml.XPath", "4.3.0" }, + { "System.Xml.XPath.XDocument", "4.3.0" }, + }; + + internal static void Register() => FrameworkPackages.Register(Instance); + } +} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netstandard2.1.cs b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netstandard2.1.cs new file mode 100644 index 000000000000..5b6aeb282854 --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/FrameworkPackages.netstandard2.1.cs @@ -0,0 +1,50 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; + +/// +/// Framework packages for .NETStandard,Version=v2.1. +/// +internal partial class FrameworkPackages +{ + internal static class NETStandard21 + { + internal static FrameworkPackages Instance { get; } = new(NetStandard21, FrameworkNames.NetStandardLibrary, NETStandard20.Instance) + { + { "System.Buffers", "4.5.1" }, + { "System.Collections.Concurrent", "4.3.0" }, + { "System.Collections.Immutable", "1.4.0" }, + { "System.ComponentModel", "4.3.0" }, + { "System.ComponentModel.Composition", "4.5.0" }, + { "System.ComponentModel.EventBasedAsync", "4.3.0" }, + { "System.Diagnostics.Contracts", "4.3.0" }, + { "System.Dynamic.Runtime", "4.3.0" }, + { "System.Linq.Queryable", "4.3.0" }, + { "System.Memory", "4.5.5" }, + { "System.Net.Requests", "4.3.0" }, + { "System.Net.WebHeaderCollection", "4.3.0" }, + { "System.Numerics.Vectors", "4.5.0" }, + { "System.ObjectModel", "4.3.0" }, + { "System.Private.DataContractSerialization", "4.3.0" }, + { "System.Reflection.DispatchProxy", "4.5.1" }, + { "System.Reflection.Emit", "4.7.0" }, + { "System.Reflection.Emit.ILGeneration", "4.7.0" }, + { "System.Reflection.Emit.Lightweight", "4.7.0" }, + { "System.Reflection.TypeExtensions", "4.3.0" }, + { "System.Runtime.Loader", "4.3.0" }, + { "System.Runtime.Numerics", "4.3.0" }, + { "System.Runtime.Serialization.Json", "4.3.0" }, + { "System.Security.AccessControl", "4.4.0" }, + { "System.Security.Cryptography.Xml", "4.4.0" }, + { "System.Security.Principal", "4.3.0" }, + { "System.Security.Principal.Windows", "4.4.0" }, + { "System.Threading", "4.3.0" }, + { "System.Threading.Tasks.Extensions", "4.5.4" }, + { "System.Threading.Tasks.Parallel", "4.3.0" }, + { "System.Xml.XDocument", "4.3.0" }, + { "System.Xml.XmlSerializer", "4.3.0" }, + }; + + internal static void Register() => FrameworkPackages.Register(Instance); + } +} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/Readme.md b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/Readme.md new file mode 100644 index 000000000000..cbf05a6a5db2 --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages/Readme.md @@ -0,0 +1,3 @@ +The code in this folder was copied from https://github.com/microsoft/component-detection/tree/main/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages + +In the future, we plan to work on a different process for acquiring and updating this data, but this is an easy way to get the prune package reference support working. \ No newline at end of file diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/GenerateDepsFile.cs b/src/Tasks/Microsoft.NET.Build.Tasks/GenerateDepsFile.cs index 549376a1f9c5..816b94b2b580 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/GenerateDepsFile.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/GenerateDepsFile.cs @@ -64,8 +64,6 @@ public class GenerateDepsFile : TaskBase public ITaskItem CompilerOptions { get; set; } - public ITaskItem[] ExcludeFromPublishPackageReferences { get; set; } = Array.Empty(); - public ITaskItem[] RuntimeStorePackages { get; set; } // NuGet compilation assets @@ -234,7 +232,6 @@ bool ShouldIncludeRuntimeAsset(ITaskItem item) .WithDirectReferences(directReferences) .WithDependencyReferences(dependencyReferences) .WithReferenceProjectInfos(referenceProjects) - .WithExcludeFromPublishAssets(PackageReferenceConverter.GetPackageIds(ExcludeFromPublishPackageReferences)) .WithRuntimePackAssets(runtimePackAssets) .WithCompilationOptions(compilationOptions) .WithReferenceAssembliesPath(FrameworkReferenceResolver.GetDefaultReferenceAssembliesPath()) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/GetPackagesToPrune.cs b/src/Tasks/Microsoft.NET.Build.Tasks/GetPackagesToPrune.cs new file mode 100644 index 000000000000..07d087be1721 --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/GetPackagesToPrune.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Microsoft.ComponentDetection.Detectors.NuGet; +using NuGet.Frameworks; +using NuGet.Versioning; + +namespace Microsoft.NET.Build.Tasks +{ + public class GetPackagesToPrune : TaskBase + { + [Required] + public string TargetFrameworkIdentifier { get; set; } + + [Required] + public string TargetFrameworkVersion { get; set; } + + [Required] + public ITaskItem[] FrameworkReferences { get; set; } + + public string TargetingPackRoot { get; set; } + + [Output] + public ITaskItem[] PackagesToPrune { get; set; } + + class CacheKey + { + public string TargetFrameworkIdentifier { get; set; } + public string TargetFrameworkVersion { get; set; } + public HashSet FrameworkReferences { get; set; } + + public override bool Equals(object? obj) => obj is CacheKey key && + TargetFrameworkIdentifier == key.TargetFrameworkIdentifier && + TargetFrameworkVersion == key.TargetFrameworkVersion && + FrameworkReferences.SetEquals(key.FrameworkReferences); + public override int GetHashCode() + { +#if NET + var hashCode = new HashCode(); + hashCode.Add(TargetFrameworkIdentifier); + hashCode.Add(TargetFrameworkVersion); + foreach (var frameworkReference in FrameworkReferences) + { + hashCode.Add(frameworkReference); + } + return hashCode.ToHashCode(); +#else + int hashCode = 1436330440; + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(TargetFrameworkIdentifier); + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(TargetFrameworkVersion); + + foreach (var frameworkReference in FrameworkReferences) + { + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(frameworkReference); + } + return hashCode; +#endif + } + } + + + protected override void ExecuteCore() + { + + // Filter out transitive framework references. Normally they wouldn't be passed to this task, but in Visual Studio design-time builds + // the ResolvePackageAssets and AddTransitiveFrameworkReferences targets may have already run. Filtering these references out should + // avoid a bug similar to https://github.com/dotnet/sdk/issues/14641 + var filteredFrameworkReferences = FrameworkReferences.Where( + i => i.GetMetadata("IsTransitiveFrameworkReference") is string transitiveVal && !transitiveVal.Equals("true", StringComparison.OrdinalIgnoreCase)).ToList(); + + CacheKey key = new() + { + TargetFrameworkIdentifier = TargetFrameworkIdentifier, + TargetFrameworkVersion = TargetFrameworkVersion, + FrameworkReferences = filteredFrameworkReferences.Select(i => i.ItemSpec).ToHashSet() + }; + + // Cache framework package values per build + var existingResult = BuildEngine4.GetRegisteredTaskObject(key, RegisteredTaskObjectLifetime.Build); + if (existingResult != null) + { + PackagesToPrune = (ITaskItem[])existingResult; + return; + } + + var nugetFramework = new NuGetFramework(TargetFrameworkIdentifier, Version.Parse(TargetFrameworkVersion)); + + Dictionary packagesToPrune = new(); + + var frameworkPackages = FrameworkPackages.GetFrameworkPackages(nugetFramework, filteredFrameworkReferences.Select(fr => fr.ItemSpec).ToArray(), TargetingPackRoot) + .SelectMany(packages => packages); + + foreach (var kvp in frameworkPackages) + { + if (packagesToPrune.TryGetValue(kvp.Key, out NuGetVersion existingVersion)) + { + if (kvp.Value > existingVersion) + { + packagesToPrune[kvp.Key] = kvp.Value; + } + } + else + { + packagesToPrune[kvp.Key] = kvp.Value; + } + } + + PackagesToPrune = packagesToPrune.Select(p => + { + var item = new TaskItem(p.Key); + item.SetMetadata("Version", p.Value.ToString()); + return item; + }).ToArray(); + + BuildEngine4.RegisterTaskObject(key, PackagesToPrune, RegisteredTaskObjectLifetime.Build, true); + } + } +} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj b/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj index 52221880aa37..4ae83a699e2e 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj +++ b/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj @@ -125,6 +125,10 @@ + + + + <_NugetBuildTasksPackPath>$(NuGetPackageRoot)nuget.build.tasks.pack\$(NuGetBuildTasksPackageVersion) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs index 3fec1be83da0..e494e717d04f 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs @@ -111,7 +111,7 @@ public class ProcessFrameworkReferences : TaskBase public bool UsingMicrosoftNETSdkWebAssembly { get; set; } - public bool UsingMicrosoftNETSdkRazor { get; set; } + public bool RequiresAspNetWebAssets { get; set; } [Required] public string NETCoreSdkRuntimeIdentifier { get; set; } @@ -502,7 +502,7 @@ protected override void ExecuteCore() AddToolPack(ToolPackType.WebAssemblySdk, _normalizedTargetFrameworkVersion, packagesToDownload, implicitPackageReferences); } - if (UsingMicrosoftNETSdkRazor && _normalizedTargetFrameworkVersion.Major >= 10) + if (RequiresAspNetWebAssets && _normalizedTargetFrameworkVersion.Major >= 10) { if (AddToolPack(ToolPackType.AspNetCore, _normalizedTargetFrameworkVersion, packagesToDownload, implicitPackageReferences) is not ToolPackSupport.Supported) { diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets index 6c484d0c4c16..f3cd6863bc4b 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets @@ -32,6 +32,15 @@ Copyright (c) .NET Foundation. All rights reserved. <_FirstTargetFrameworkVersionToSupportSingleFileAnalyzer>$([MSBuild]::GetTargetFrameworkVersion('$(_FirstTargetFrameworkToSupportSingleFile)')) + + + + + + + + + Always @@ -1242,7 +1251,6 @@ Copyright (c) .NET Foundation. All rights reserved. PlatformLibraryName="$(MicrosoftNETPlatformLibrary)" RuntimeFrameworks="@(RuntimeFramework)" CompilerOptions="@(DependencyFileCompilerOptions)" - ExcludeFromPublishPackageReferences="@(_ExcludeFromPublishPackageReference)" RuntimeStorePackages="@(RuntimeStorePackages)" CompileReferences="@(ResolvedCompileFileDefinitions)" ResolvedNuGetFiles="@(_ResolvedNuGetFilesForPublish)" diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets index c38f4e38e9d5..e4923fb2c1e9 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets @@ -18,6 +18,7 @@ Copyright (c) .NET Foundation. All rights reserved. + @@ -49,7 +50,19 @@ Copyright (c) .NET Foundation. All rights reserved. - + + + + + + + + + - - - diff --git a/src/Tasks/Microsoft.NET.slnf b/src/Tasks/Microsoft.NET.slnf index b00e01434e0e..916ea614fea4 100644 --- a/src/Tasks/Microsoft.NET.slnf +++ b/src/Tasks/Microsoft.NET.slnf @@ -12,7 +12,7 @@ "src\\Compatibility\\ApiCompat\\Microsoft.DotNet.ApiCompat.Tool\\Microsoft.DotNet.ApiCompat.Tool.csproj", "src\\Compatibility\\ApiCompat\\Microsoft.DotNet.ApiCompatibility\\Microsoft.DotNet.ApiCompatibility.csproj", "src\\Compatibility\\ApiCompat\\Microsoft.DotNet.PackageValidation\\Microsoft.DotNet.PackageValidation.csproj", - "src\\Microsoft.DotNet.ApiSymbolExtensions\\Microsoft.DotNet.ApiSymbolExtensions.csproj", + "src\\Compatibility\\Microsoft.DotNet.ApiSymbolExtensions\\Microsoft.DotNet.ApiSymbolExtensions.csproj", "src\\Microsoft.DotNet.TemplateLocator\\Microsoft.DotNet.TemplateLocator.csproj", "src\\Microsoft.Win32.Msi\\Microsoft.Win32.Msi.csproj", "src\\Resolvers\\Microsoft.DotNet.MSBuildSdkResolver\\Microsoft.DotNet.MSBuildSdkResolver.csproj", diff --git a/src/WebSdk/ProjectSystem/Targets/Microsoft.NET.Sdk.Web.ProjectSystem.targets b/src/WebSdk/ProjectSystem/Targets/Microsoft.NET.Sdk.Web.ProjectSystem.targets index 40c90c1ec47a..cbfd27505de0 100644 --- a/src/WebSdk/ProjectSystem/Targets/Microsoft.NET.Sdk.Web.ProjectSystem.targets +++ b/src/WebSdk/ProjectSystem/Targets/Microsoft.NET.Sdk.Web.ProjectSystem.targets @@ -108,4 +108,9 @@ Copyright (c) .NET Foundation. All rights reserved. + + + true + + diff --git a/src/WebSdk/Publish/Tasks/WebConfigTelemetry.cs b/src/WebSdk/Publish/Tasks/WebConfigTelemetry.cs index db4ae37eafa6..929acf321741 100644 --- a/src/WebSdk/Publish/Tasks/WebConfigTelemetry.cs +++ b/src/WebSdk/Publish/Tasks/WebConfigTelemetry.cs @@ -66,7 +66,10 @@ public class WebConfigTelemetry return null; } - IEnumerable solutionFiles = Directory.EnumerateFiles(solutionDirectory, "*.sln", SearchOption.TopDirectoryOnly); + IEnumerable solutionFiles = [ + ..Directory.EnumerateFiles(solutionDirectory, "*.sln", SearchOption.TopDirectoryOnly), + ..Directory.EnumerateFiles(solutionDirectory, "*.slnx", SearchOption.TopDirectoryOnly) + ]; foreach (string solutionFile in solutionFiles) { string? projectGuid = GetProjectGuid(solutionFile, projectFileFullPath); diff --git a/test/EndToEnd.Tests/ProjectBuildTests.cs b/test/EndToEnd.Tests/ProjectBuildTests.cs index 9c5e9b5998d1..e683e1e6efd2 100644 --- a/test/EndToEnd.Tests/ProjectBuildTests.cs +++ b/test/EndToEnd.Tests/ProjectBuildTests.cs @@ -410,8 +410,7 @@ private static string DetectExpectedDefaultFramework(string template = "") if (latestMajorVersion == 10) { // TODO: This block need to be updated when every template updates their default tfm. - // Currently winforms updated their default templates target but not others. - if (template.StartsWith("winforms") || template.StartsWith("wpf")) + if (template.StartsWith("wpf")) { return $"net9.0"; } diff --git a/test/HelixTasks/SDKCustomCreateXUnitWorkItemsWithTestExclusion.cs b/test/HelixTasks/SDKCustomCreateXUnitWorkItemsWithTestExclusion.cs index 3d30bc649adf..c7bcc6a206d3 100644 --- a/test/HelixTasks/SDKCustomCreateXUnitWorkItemsWithTestExclusion.cs +++ b/test/HelixTasks/SDKCustomCreateXUnitWorkItemsWithTestExclusion.cs @@ -64,7 +64,7 @@ public override bool Execute() /// /// The asynchronous execution method for this MSBuild task which verifies the integrity of required properties - /// and validates their formatting, specifically determining whether the provided xUnit project data have a + /// and validates their formatting, specifically determining whether the provided xUnit project data have a /// one-to-one mapping. It then creates this mapping before asynchronously preparing the HelixWorkItem TaskItem /// objects via the PrepareWorkItem method. /// @@ -153,11 +153,13 @@ private async Task ExecuteAsync() var partitionedWorkItem = new List(); foreach (var assemblyPartitionInfo in assemblyPartitionInfos) { - string command; + string enableDiagLogging = IsPosixShell ? "-d $HELIX_WORKITEM_UPLOAD_ROOT//dotnetTestLog.log" : "-d %HELIX_WORKITEM_UPLOAD_ROOT%\\dotnetTestLog.log"; + arguments = string.IsNullOrEmpty(arguments) ? "" : "-- " + arguments; var testFilter = string.IsNullOrEmpty(assemblyPartitionInfo.ClassListArgumentString) ? "" : $"--filter \"{assemblyPartitionInfo.ClassListArgumentString}\""; - command = $"{driver} test {assemblyName} -e HELIX_WORK_ITEM_TIMEOUT={timeout} {testExecutionDirectory} {msbuildAdditionalSdkResolverFolder} " + - $"{(XUnitArguments != null ? " " + XUnitArguments : "")} --results-directory .{Path.DirectorySeparatorChar} --logger trx --logger \"console;verbosity=detailed\" --blame-hang --blame-hang-timeout 15m {testFilter} -- {arguments}"; + + string command = $"{driver} test {assemblyName} -e HELIX_WORK_ITEM_TIMEOUT={timeout} {testExecutionDirectory} {msbuildAdditionalSdkResolverFolder} " + + $"{(XUnitArguments != null ? " " + XUnitArguments : "")} --results-directory .{Path.DirectorySeparatorChar} --logger trx --logger \"console;verbosity=detailed\" --blame-hang --blame-hang-timeout 15m {testFilter} {enableDiagLogging} {arguments}"; Log.LogMessage($"Creating work item with properties Identity: {assemblyName}, PayloadDirectory: {publishDirectory}, Command: {command}"); diff --git a/test/Microsoft.DotNet.ApiCompatibility.Tests/Rules/AttributesMustMatchTests.cs b/test/Microsoft.DotNet.ApiCompatibility.Tests/Rules/AttributesMustMatchTests.cs index 11d9b98aea4f..993a6b98cabf 100644 --- a/test/Microsoft.DotNet.ApiCompatibility.Tests/Rules/AttributesMustMatchTests.cs +++ b/test/Microsoft.DotNet.ApiCompatibility.Tests/Rules/AttributesMustMatchTests.cs @@ -20,7 +20,7 @@ public class AttributesMustMatchTests * - ReturnValues * - Constructors * - Generic Parameters - * + * * Grouped into: * - Type * - Member @@ -28,9 +28,6 @@ public class AttributesMustMatchTests private static readonly TestRuleFactory s_ruleFactory = new((settings, context) => new AttributesMustMatch(settings, context)); - private static ISymbolFilter GetAccessibilityAndAttributeSymbolFiltersAsComposite(params string[] excludeAttributeFiles) => - new CompositeSymbolFilter().Add(new AccessibilitySymbolFilter(false)).Add(new DocIdSymbolFilter(excludeAttributeFiles)); - public static TheoryData TypesCases => new() { // No change to type's attributes @@ -39,7 +36,7 @@ private static ISymbolFilter GetAccessibilityAndAttributeSymbolFiltersAsComposit namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -56,7 +53,7 @@ public class First {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -77,7 +74,7 @@ public class First {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -94,7 +91,7 @@ public class First {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -116,7 +113,7 @@ public class First {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -133,7 +130,7 @@ public class First {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -156,7 +153,7 @@ public class First {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -173,7 +170,7 @@ public class First {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -196,7 +193,7 @@ public class First {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -212,7 +209,7 @@ public class First {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -311,7 +308,7 @@ public class First {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -337,7 +334,7 @@ public void F() {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -370,7 +367,7 @@ public void F() {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -396,7 +393,7 @@ public class First { namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -429,7 +426,7 @@ public class First { namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -457,7 +454,7 @@ public class First { namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -492,7 +489,7 @@ public class First { namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -518,7 +515,7 @@ public First() {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -551,7 +548,7 @@ public First() {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -577,7 +574,7 @@ public class First { namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -610,7 +607,7 @@ public class First { namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -634,7 +631,7 @@ public void F([Bar] int v, [Foo(""S"", A = true, B = 0)] string s) {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -666,7 +663,7 @@ public void F([Baz] int v, [Foo(""T"")] string s) {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -687,7 +684,7 @@ public class First<[Bar] T1, [Foo(""S"", A = true, B = 0)] T2> {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -716,7 +713,7 @@ public class First<[Baz] T1, [Foo(""T"")] T2> {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -740,7 +737,7 @@ public class First { namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -792,7 +789,7 @@ public class First {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -815,7 +812,7 @@ public class First {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -832,7 +829,7 @@ public class First {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -1332,7 +1329,7 @@ public void EnsureDiagnosticIsReported(string leftSyntax, string rightSyntax, Co IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(s_ruleFactory); - differ.Settings.AttributeDataSymbolFilter = GetAccessibilityAndAttributeSymbolFiltersAsComposite(filePath); + differ.Settings.AttributeDataSymbolFilter = SymbolFilterFactory.GetFilterFromFiles([filePath], respectInternals: false); IEnumerable actual = differ.GetDifferences(left, right); @@ -1349,7 +1346,7 @@ public void EnsureStrictModeReported(string leftSyntax, string rightSyntax, Comp IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(s_ruleFactory, new ApiComparerSettings(strictMode: true)); - differ.Settings.AttributeDataSymbolFilter = GetAccessibilityAndAttributeSymbolFiltersAsComposite(filePath); + differ.Settings.AttributeDataSymbolFilter = SymbolFilterFactory.GetFilterFromFiles([filePath], respectInternals: false); IEnumerable actual = differ.GetDifferences(left, right); @@ -1366,7 +1363,7 @@ public void TestExclusionsFilteredOut() namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -1382,7 +1379,7 @@ public class First {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -1398,7 +1395,7 @@ public class First {} IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(s_ruleFactory); - differ.Settings.AttributeDataSymbolFilter = GetAccessibilityAndAttributeSymbolFiltersAsComposite(filePath); + differ.Settings.AttributeDataSymbolFilter = SymbolFilterFactory.GetFilterFromFiles([filePath], respectInternals: false); IEnumerable actual = differ.GetDifferences(left, right); @@ -1418,7 +1415,7 @@ public void AttributesExcludedButMembersValidated() namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -1433,7 +1430,7 @@ public class First {} namespace CompatTests { using System; - + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class FooAttribute : Attribute { public FooAttribute(String s) {} @@ -1448,7 +1445,7 @@ public class First {} IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(ruleFactory, new ApiComparerSettings(strictMode: true)); - differ.Settings.AttributeDataSymbolFilter = GetAccessibilityAndAttributeSymbolFiltersAsComposite(filePath); + differ.Settings.AttributeDataSymbolFilter = SymbolFilterFactory.GetFilterFromFiles([filePath], respectInternals: false); IEnumerable actual = differ.GetDifferences(left, right).ToArray(); diff --git a/test/Microsoft.DotNet.ApiSymbolExtensions.Tests/AssemblySymbolLoaderTests.cs b/test/Microsoft.DotNet.ApiSymbolExtensions.Tests/AssemblySymbolLoaderTests.cs index 35886f8cbf05..5fb4b0f17947 100644 --- a/test/Microsoft.DotNet.ApiSymbolExtensions.Tests/AssemblySymbolLoaderTests.cs +++ b/test/Microsoft.DotNet.ApiSymbolExtensions.Tests/AssemblySymbolLoaderTests.cs @@ -5,6 +5,7 @@ using System.Collections.Concurrent; using System.Reflection; +using System.Text.RegularExpressions; using Microsoft.CodeAnalysis; using Microsoft.DotNet.Cli.Utils; @@ -264,21 +265,26 @@ public void LoadAssemblyResolveReferences_WarnsWhenEnabled(bool resolveReference var assetInfo = GetSimpleTestAsset(); TestLog log = new(); AssemblySymbolLoader loader = new(log, resolveAssemblyReferences: resolveReferences); - loader.LoadAssembly(Path.Combine(assetInfo.OutputDirectory, assetInfo.TestAsset.TestProject.Name + ".dll")); + string assemblyPath = Path.Combine(assetInfo.OutputDirectory, assetInfo.TestAsset.TestProject.Name + ".dll"); + loader.LoadAssembly(assemblyPath); if (resolveReferences) { - Assert.True(log.HasLoggedWarnings); + // Temporarily downgrade assembly reference load warnings to messages: https://github.com/dotnet/sdk/issues/46236 - string expectedReference = "System.Runtime.dll"; + // Assert.True(log.HasLoggedWarnings); - if (TargetFrameworks.StartsWith("net4", StringComparison.OrdinalIgnoreCase)) - { - expectedReference = "mscorlib.dll"; - } + // string expectedReference = "System.Runtime.dll"; - List expected = [$"{AssemblySymbolLoader.AssemblyReferenceNotFoundErrorCode} Could not resolve reference '{expectedReference}' in any of the provided search directories."]; - Assert.Equal(expected, log.Warnings, StringComparer.CurrentCultureIgnoreCase); + // if (TargetFrameworks.StartsWith("net4", StringComparison.OrdinalIgnoreCase)) + // { + // expectedReference = "mscorlib.dll"; + // } + + // Assert.Single(log.Warnings); + // Assert.Matches($"CP1002.*?'{Regex.Escape(expectedReference)}'.*?'{Regex.Escape(assemblyPath)}'.*", log.Warnings.Single()); + + Assert.Empty(log.Warnings); } else { diff --git a/test/Microsoft.DotNet.ApiSymbolExtensions.Tests/SymbolFactory.cs b/test/Microsoft.DotNet.ApiSymbolExtensions.Tests/SymbolFactory.cs index dce5d5266a33..9f5abe5252bb 100644 --- a/test/Microsoft.DotNet.ApiSymbolExtensions.Tests/SymbolFactory.cs +++ b/test/Microsoft.DotNet.ApiSymbolExtensions.Tests/SymbolFactory.cs @@ -31,12 +31,13 @@ public static string EmitAssemblyFromSyntax(string syntax, } public static Stream EmitAssemblyStreamFromSyntax(string syntax, + IEnumerable> diagnosticOptions = null, bool enableNullable = false, byte[] publicKey = null, [CallerMemberName] string assemblyName = "", bool allowUnsafe = false) { - CSharpCompilation compilation = CreateCSharpCompilationFromSyntax(syntax, assemblyName, enableNullable, publicKey, allowUnsafe); + CSharpCompilation compilation = CreateCSharpCompilationFromSyntax(syntax, assemblyName, enableNullable, publicKey, allowUnsafe, diagnosticOptions); Assert.Empty(compilation.GetDiagnostics()); @@ -76,9 +77,9 @@ public static IAssemblySymbol GetAssemblyFromSyntaxWithReferences(string syntax, return compilation.Assembly; } - private static CSharpCompilation CreateCSharpCompilationFromSyntax(string syntax, string name, bool enableNullable, byte[] publicKey, bool allowUnsafe) + private static CSharpCompilation CreateCSharpCompilationFromSyntax(string syntax, string name, bool enableNullable, byte[] publicKey, bool allowUnsafe, IEnumerable> diagnosticOptions = null) { - CSharpCompilation compilation = CreateCSharpCompilation(name, enableNullable, publicKey, allowUnsafe); + CSharpCompilation compilation = CreateCSharpCompilation(name, enableNullable, publicKey, allowUnsafe, diagnosticOptions); return compilation.AddSyntaxTrees(GetSyntaxTree(syntax)); } @@ -94,7 +95,7 @@ private static SyntaxTree GetSyntaxTree(string syntax) return CSharpSyntaxTree.ParseText(syntax, ParseOptions); } - private static CSharpCompilation CreateCSharpCompilation(string name, bool enableNullable, byte[] publicKey, bool allowUnsafe) + private static CSharpCompilation CreateCSharpCompilation(string name, bool enableNullable, byte[] publicKey, bool allowUnsafe, IEnumerable> diagnosticOptions = null) { bool publicSign = publicKey != null ? true : false; var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, @@ -102,7 +103,7 @@ private static CSharpCompilation CreateCSharpCompilation(string name, bool enabl cryptoPublicKey: publicSign ? publicKey.ToImmutableArray() : default, nullableContextOptions: enableNullable ? NullableContextOptions.Enable : NullableContextOptions.Disable, allowUnsafe: allowUnsafe, - specificDiagnosticOptions: DiagnosticOptions); + specificDiagnosticOptions: diagnosticOptions ?? DiagnosticOptions); return CSharpCompilation.Create(name, options: compilationOptions, references: DefaultReferences); } diff --git a/test/Microsoft.DotNet.ApiSymbolExtensions.Tests/SymbolFilterFactoryTests.cs b/test/Microsoft.DotNet.ApiSymbolExtensions.Tests/SymbolFilterFactoryTests.cs new file mode 100644 index 000000000000..220d0c2ee436 --- /dev/null +++ b/test/Microsoft.DotNet.ApiSymbolExtensions.Tests/SymbolFilterFactoryTests.cs @@ -0,0 +1,114 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#nullable disable + +using Xunit; +using Microsoft.DotNet.ApiSymbolExtensions.Filtering; +using Microsoft.CodeAnalysis; + +namespace Microsoft.DotNet.ApiSymbolExtensions.Tests; + +public class SymbolFilterFactoryTests +{ + [Theory] + [InlineData(true)] + [InlineData(false)] + public void Test_FilterFromFiles(bool includeCustomType) + { + Test_FilterFromFiles_Internal(includeCustomType, accessibilitySymbolFilter: null); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void Test_FilterFromFiles_CustomAccessibilityFilter(bool includeCustomType) + { + Test_FilterFromFiles_Internal(includeCustomType, new AccessibilitySymbolFilter(includeInternalSymbols: true)); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void Test_FilterFromList(bool includeCustomType) + { + Test_FilterFromList_Internal(includeCustomType, accessibilitySymbolFilter: null); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void Test_FilterFromList_WithCustomAccessibilityFilter(bool includeCustomType) + { + Test_FilterFromList_Internal(includeCustomType, new AccessibilitySymbolFilter(includeInternalSymbols: true)); + } + + private void Test_FilterFromFiles_Internal(bool includeCustomType, AccessibilitySymbolFilter accessibilitySymbolFilter) + { + using TempDirectory root = new(); + string filePath = Path.Combine(root.DirPath, "exclusions.txt"); + using (FileStream fileStream = File.Create(filePath)) + { + using StreamWriter writer = new(fileStream); + writer.WriteLine("T:System.Int32"); + writer.WriteLine("T:System.String"); + if (!includeCustomType) + { + writer.WriteLine("T:MyNamespace.MyClass"); + } + } + + CompositeSymbolFilter filter = SymbolFilterFactory.GetFilterFromFiles( + apiExclusionFilePaths: [filePath], + accessibilitySymbolFilter: accessibilitySymbolFilter, + respectInternals: true, + includeEffectivelyPrivateSymbols: true, + includeExplicitInterfaceImplementationSymbols: true) as CompositeSymbolFilter; + + Test_GetFilter_Internal(filter, includeCustomType); + } + + private void Test_FilterFromList_Internal(bool includeCustomType, AccessibilitySymbolFilter accessibilitySymbolFilter) + { + List exclusions = ["T:System.Int32", "T:System.String"]; + if (!includeCustomType) + { + exclusions.Add("T:MyNamespace.MyClass"); + } + + CompositeSymbolFilter filter = SymbolFilterFactory.GetFilterFromList( + apiExclusionList: exclusions.ToArray(), + accessibilitySymbolFilter: accessibilitySymbolFilter, + respectInternals: true, + includeEffectivelyPrivateSymbols: true, + includeExplicitInterfaceImplementationSymbols: true) as CompositeSymbolFilter; + + Test_GetFilter_Internal(filter, includeCustomType); + } + + private void Test_GetFilter_Internal(CompositeSymbolFilter compositeFilter, bool includeCustomType) + { + Assert.NotNull(compositeFilter); + + Assert.Equal(3, compositeFilter.Filters.Count); + + DocIdSymbolFilter docIdFilter = compositeFilter.Filters[0] as DocIdSymbolFilter; + Assert.NotNull(docIdFilter); + + ImplicitSymbolFilter implicitFilter = compositeFilter.Filters[1] as ImplicitSymbolFilter; + Assert.NotNull(implicitFilter); + + AccessibilitySymbolFilter accessibilityFilter = compositeFilter.Filters[2] as AccessibilitySymbolFilter; + Assert.NotNull(accessibilityFilter); + + IAssemblySymbol assemblySymbol = SymbolFactory.GetAssemblyFromSyntax(@" +namespace MyNamespace +{ + public class MyClass { } +}"); + Assert.NotNull(assemblySymbol); + INamedTypeSymbol myClass = assemblySymbol.GetTypeByMetadataName("MyNamespace.MyClass"); + Assert.NotNull(myClass); + Assert.Equal(includeCustomType, docIdFilter.Include(myClass)); + } +} diff --git a/test/Microsoft.DotNet.Cli.Sln.Internal.Tests/Microsoft.DotNet.Cli.Sln.Internal.Tests.cs b/test/Microsoft.DotNet.Cli.Sln.Internal.Tests/Microsoft.DotNet.Cli.Sln.Internal.Tests.cs deleted file mode 100644 index 036ec4d29419..000000000000 --- a/test/Microsoft.DotNet.Cli.Sln.Internal.Tests/Microsoft.DotNet.Cli.Sln.Internal.Tests.cs +++ /dev/null @@ -1,532 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#nullable disable - -using System.Runtime.CompilerServices; - -namespace Microsoft.DotNet.Cli.Sln.Internal.Tests -{ - public class GivenAnSlnFile : SdkTest - { - private const string SolutionModified = @" -Microsoft Visual Studio Solution File, Format Version 14.00 -# Visual Studio 16 -VisualStudioVersion = 16.0.26006.2 -MinimumVisualStudioVersion = 11.0.40219.1 -Project(""{7072A694-548F-4CAE-A58F-12D257D5F486}"") = ""AppModified"", ""AppModified\AppModified.csproj"", ""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.ActiveCfg = Debug|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.Build.0 = Debug|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.ActiveCfg = Debug|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.Build.0 = Debug|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.Build.0 = Release|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.ActiveCfg = Release|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.Build.0 = Release|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.ActiveCfg = Release|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.Build.0 = Release|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = TRUE - EndGlobalSection -EndGlobal -"; - - private const string SolutionWithAppAndLibProjects = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26006.2 -MinimumVisualStudioVersion = 10.0.40219.1 -Project(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""App"", ""App\App.csproj"", ""{7072A694-548F-4CAE-A58F-12D257D5F486}"" -EndProject -Project(""{13B669BE-BB05-4DDF-9536-439F39A36129}"") = ""Lib"", ""..\Lib\Lib.csproj"", ""{21D9159F-60E6-4F65-BC6B-D01B71B15FFC}"" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.ActiveCfg = Debug|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.Build.0 = Debug|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.ActiveCfg = Debug|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.Build.0 = Debug|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.Build.0 = Release|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.ActiveCfg = Release|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.Build.0 = Release|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.ActiveCfg = Release|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.Build.0 = Release|x86 - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Debug|x64.ActiveCfg = Debug|x64 - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Debug|x64.Build.0 = Debug|x64 - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Debug|x86.ActiveCfg = Debug|x86 - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Debug|x86.Build.0 = Debug|x86 - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Release|Any CPU.Build.0 = Release|Any CPU - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Release|x64.ActiveCfg = Release|x64 - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Release|x64.Build.0 = Release|x64 - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Release|x86.ActiveCfg = Release|x86 - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Release|x86.Build.0 = Release|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal -"; - - public GivenAnSlnFile(ITestOutputHelper log) : base(log) - { - } - - private string CreateFile([CallerMemberName] string callerName = null, string identifier = null) - { - var folder = _testAssetsManager.CreateTestDirectory(testName: callerName + identifier); - var filename = Path.Combine(folder.Path, Guid.NewGuid().ToString() + ".tmp"); - using (new FileStream(filename, FileMode.CreateNew)) { } - return filename; - } - - - [Fact] - public void WhenGivenAValidSlnFileItReadsAndVerifiesContents() - { - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionWithAppAndLibProjects); - - SlnFile slnFile = SlnFile.Read(tmpFile); - - Console.WriteLine(new - { - slnFile_FormatVersion = slnFile.FormatVersion, - slnFile_ProductDescription = slnFile.ProductDescription, - slnFile_VisualStudioVersion = slnFile.VisualStudioVersion, - slnFile_MinimumVisualStudioVersion = slnFile.MinimumVisualStudioVersion, - slnFile_BaseDirectory = slnFile.BaseDirectory, - slnFile_FullPath = slnFile.FullPath, - tmpFilePath = tmpFile - }.ToString()); - - slnFile.FormatVersion.Should().Be("12.00"); - slnFile.ProductDescription.Should().Be("Visual Studio 15"); - slnFile.VisualStudioVersion.Should().Be("15.0.26006.2"); - slnFile.MinimumVisualStudioVersion.Should().Be("10.0.40219.1"); - slnFile.BaseDirectory.Should().Be(Path.GetDirectoryName(tmpFile)); - slnFile.FullPath.Should().Be(Path.GetFullPath(tmpFile)); - - slnFile.Projects.Count.Should().Be(2); - var project = slnFile.Projects[0]; - project.Id.Should().Be("{7072A694-548F-4CAE-A58F-12D257D5F486}"); - project.TypeGuid.Should().Be("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"); - project.Name.Should().Be("App"); - project.FilePath.Should().Be(Path.Combine("App", "App.csproj")); - project = slnFile.Projects[1]; - project.Id.Should().Be("{21D9159F-60E6-4F65-BC6B-D01B71B15FFC}"); - project.TypeGuid.Should().Be("{13B669BE-BB05-4DDF-9536-439F39A36129}"); - project.Name.Should().Be("Lib"); - project.FilePath.Should().Be(Path.Combine("..", "Lib", "Lib.csproj")); - - slnFile.SolutionConfigurationsSection.Count.Should().Be(6); - slnFile.SolutionConfigurationsSection - .GetValue("Debug|Any CPU", string.Empty) - .Should().Be("Debug|Any CPU"); - slnFile.SolutionConfigurationsSection - .GetValue("Debug|x64", string.Empty) - .Should().Be("Debug|x64"); - slnFile.SolutionConfigurationsSection - .GetValue("Debug|x86", string.Empty) - .Should().Be("Debug|x86"); - slnFile.SolutionConfigurationsSection - .GetValue("Release|Any CPU", string.Empty) - .Should().Be("Release|Any CPU"); - slnFile.SolutionConfigurationsSection - .GetValue("Release|x64", string.Empty) - .Should().Be("Release|x64"); - slnFile.SolutionConfigurationsSection - .GetValue("Release|x86", string.Empty) - .Should().Be("Release|x86"); - - slnFile.ProjectConfigurationsSection.Count.Should().Be(2); - var projectConfigSection = slnFile - .ProjectConfigurationsSection - .GetPropertySet("{7072A694-548F-4CAE-A58F-12D257D5F486}"); - projectConfigSection.Count.Should().Be(12); - projectConfigSection - .GetValue("Debug|Any CPU.ActiveCfg", string.Empty) - .Should().Be("Debug|Any CPU"); - projectConfigSection - .GetValue("Debug|Any CPU.Build.0", string.Empty) - .Should().Be("Debug|Any CPU"); - projectConfigSection - .GetValue("Debug|x64.ActiveCfg", string.Empty) - .Should().Be("Debug|x64"); - projectConfigSection - .GetValue("Debug|x64.Build.0", string.Empty) - .Should().Be("Debug|x64"); - projectConfigSection - .GetValue("Debug|x86.ActiveCfg", string.Empty) - .Should().Be("Debug|x86"); - projectConfigSection - .GetValue("Debug|x86.Build.0", string.Empty) - .Should().Be("Debug|x86"); - projectConfigSection - .GetValue("Release|Any CPU.ActiveCfg", string.Empty) - .Should().Be("Release|Any CPU"); - projectConfigSection - .GetValue("Release|Any CPU.Build.0", string.Empty) - .Should().Be("Release|Any CPU"); - projectConfigSection - .GetValue("Release|x64.ActiveCfg", string.Empty) - .Should().Be("Release|x64"); - projectConfigSection - .GetValue("Release|x64.Build.0", string.Empty) - .Should().Be("Release|x64"); - projectConfigSection - .GetValue("Release|x86.ActiveCfg", string.Empty) - .Should().Be("Release|x86"); - projectConfigSection - .GetValue("Release|x86.Build.0", string.Empty) - .Should().Be("Release|x86"); - projectConfigSection = slnFile - .ProjectConfigurationsSection - .GetPropertySet("{21D9159F-60E6-4F65-BC6B-D01B71B15FFC}"); - projectConfigSection.Count.Should().Be(12); - projectConfigSection - .GetValue("Debug|Any CPU.ActiveCfg", string.Empty) - .Should().Be("Debug|Any CPU"); - projectConfigSection - .GetValue("Debug|Any CPU.Build.0", string.Empty) - .Should().Be("Debug|Any CPU"); - projectConfigSection - .GetValue("Debug|x64.ActiveCfg", string.Empty) - .Should().Be("Debug|x64"); - projectConfigSection - .GetValue("Debug|x64.Build.0", string.Empty) - .Should().Be("Debug|x64"); - projectConfigSection - .GetValue("Debug|x86.ActiveCfg", string.Empty) - .Should().Be("Debug|x86"); - projectConfigSection - .GetValue("Debug|x86.Build.0", string.Empty) - .Should().Be("Debug|x86"); - projectConfigSection - .GetValue("Release|Any CPU.ActiveCfg", string.Empty) - .Should().Be("Release|Any CPU"); - projectConfigSection - .GetValue("Release|Any CPU.Build.0", string.Empty) - .Should().Be("Release|Any CPU"); - projectConfigSection - .GetValue("Release|x64.ActiveCfg", string.Empty) - .Should().Be("Release|x64"); - projectConfigSection - .GetValue("Release|x64.Build.0", string.Empty) - .Should().Be("Release|x64"); - projectConfigSection - .GetValue("Release|x86.ActiveCfg", string.Empty) - .Should().Be("Release|x86"); - projectConfigSection - .GetValue("Release|x86.Build.0", string.Empty) - .Should().Be("Release|x86"); - - slnFile.Sections.Count.Should().Be(3); - var solutionPropertiesSection = slnFile.Sections.GetSection("SolutionProperties"); - solutionPropertiesSection.Properties.Count.Should().Be(1); - solutionPropertiesSection.Properties - .GetValue("HideSolutionNode", string.Empty) - .Should().Be("FALSE"); - } - - [Fact] - public void WhenGivenAValidReadOnlySlnFileItReadsContentsWithNoException() - { - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionWithAppAndLibProjects); - var attr = File.GetAttributes(tmpFile); - attr = attr | FileAttributes.ReadOnly; - File.SetAttributes(tmpFile, attr); - - Action act = () => SlnFile.Read(tmpFile); - act.Should().NotThrow("Because readonly file is not being modified."); - } - - [Fact] - public void WhenGivenAValidSlnFileItModifiesSavesAndVerifiesContents() - { - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionWithAppAndLibProjects); - - SlnFile slnFile = SlnFile.Read(tmpFile); - - slnFile.FormatVersion = "14.00"; - slnFile.ProductDescription = "Visual Studio 16"; - slnFile.VisualStudioVersion = "16.0.26006.2"; - slnFile.MinimumVisualStudioVersion = "11.0.40219.1"; - - slnFile.Projects.Count.Should().Be(2); - var project = slnFile.Projects[0]; - project.Id = "{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"; - project.TypeGuid = "{7072A694-548F-4CAE-A58F-12D257D5F486}"; - project.Name = "AppModified"; - project.FilePath = Path.Combine("AppModified", "AppModified.csproj"); - slnFile.Projects.Remove(slnFile.Projects[1]); - - slnFile.SolutionConfigurationsSection.Count.Should().Be(6); - slnFile.SolutionConfigurationsSection.Remove("Release|Any CPU"); - slnFile.SolutionConfigurationsSection.Remove("Release|x64"); - slnFile.SolutionConfigurationsSection.Remove("Release|x86"); - - slnFile.ProjectConfigurationsSection.Count.Should().Be(2); - var projectConfigSection = slnFile - .ProjectConfigurationsSection - .GetPropertySet("{21D9159F-60E6-4F65-BC6B-D01B71B15FFC}"); - slnFile.ProjectConfigurationsSection.Remove(projectConfigSection); - - slnFile.Sections.Count.Should().Be(3); - var solutionPropertiesSection = slnFile.Sections.GetSection("SolutionProperties"); - solutionPropertiesSection.Properties.Count.Should().Be(1); - solutionPropertiesSection.Properties.SetValue("HideSolutionNode", "TRUE"); - - slnFile.Write(); - - File.ReadAllText(tmpFile) - .Should().Be(SolutionModified); - } - - [Theory] - [InlineData("Microsoft Visual Studio Solution File, Format Version ", 1)] - [InlineData("First Line\nMicrosoft Visual Studio Solution File, Format Version ", 2)] - [InlineData("First Line\nMicrosoft Visual Studio Solution File, Format Version \nThird Line", 2)] - [InlineData("First Line\nSecondLine\nMicrosoft Visual Studio Solution File, Format Version \nFourth Line", 3)] - public void WhenGivenASolutionWithMissingHeaderVersionItThrows(string fileContents, int lineNum) - { - var tmpFile = CreateFile(identifier: fileContents.GetHashCode().ToString()); - File.WriteAllText(tmpFile, fileContents); - - Action action = () => - { - SlnFile.Read(tmpFile); - }; - - action.Should().Throw() - .WithMessage(FormatError(lineNum, LocalizableStrings.FileHeaderMissingVersionError)); - } - - [Theory] - [InlineData("Invalid Solution")] - [InlineData("Invalid Solution\nSpanning Multiple Lines")] - [InlineData("Microsoft Visual\nStudio Solution File,\nFormat Version ")] - public void WhenGivenASolutionWithMissingHeaderItThrows(string fileContents) - { - var tmpFile = CreateFile(identifier: fileContents.GetHashCode().ToString()); - File.WriteAllText(tmpFile, fileContents); - - Action action = () => - { - SlnFile.Read(tmpFile); - }; - - action.Should().Throw() - .WithMessage(LocalizableStrings.FileHeaderMissingError); - } - - [Fact] - public void WhenGivenASolutionWithMultipleGlobalSectionsItThrows() - { - const string SolutionFile = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -Global -EndGlobal -Global -EndGlobal -"; - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionFile); - - Action action = () => - { - SlnFile.Read(tmpFile); - }; - - action.Should().Throw() - .WithMessage(FormatError(5, LocalizableStrings.GlobalSectionMoreThanOnceError)); - } - - [Fact] - public void WhenGivenASolutionWithGlobalSectionNotClosedItThrows() - { - const string SolutionFile = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -Global -"; - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionFile); - - Action action = () => - { - SlnFile.Read(tmpFile); - }; - - action.Should().Throw() - .WithMessage(FormatError(3, LocalizableStrings.GlobalSectionNotClosedError)); - } - - [Fact] - public void WhenGivenASolutionWithProjectSectionNotClosedItThrows() - { - const string SolutionFile = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -Project(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""App"", ""App\App.csproj"", ""{7072A694-548F-4CAE-A58F-12D257D5F486}"" -"; - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionFile); - - Action action = () => - { - SlnFile.Read(tmpFile); - }; - - action.Should().Throw() - .WithMessage(FormatError(3, LocalizableStrings.ProjectSectionNotClosedError)); - } - - [Fact] - public void WhenGivenASolutionWithInvalidProjectSectionItThrows() - { - const string SolutionFile = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -Project""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""App"", ""App\App.csproj"", ""{7072A694-548F-4CAE-A58F-12D257D5F486}"" -EndProject -"; - - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionFile); - - Action action = () => - { - SlnFile.Read(tmpFile); - }; - - action.Should().Throw() - .WithMessage(FormatError(3, LocalizableStrings.ProjectParsingErrorFormatString, "(", 0)); - } - - [Fact] - public void WhenGivenASolutionWithInvalidSectionTypeItThrows() - { - const string SolutionFile = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -Global - GlobalSection(SolutionConfigurationPlatforms) = thisIsUnknown - EndGlobalSection -EndGlobal -"; - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionFile); - - Action action = () => - { - SlnFile.Read(tmpFile); - }; - - action.Should().Throw() - .WithMessage(FormatError(4, LocalizableStrings.InvalidSectionTypeError, "thisIsUnknown")); - } - - [Fact] - public void WhenGivenASolutionWithMissingSectionIdTypeItThrows() - { - const string SolutionFile = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -Global - GlobalSection = preSolution - EndGlobalSection -EndGlobal -"; - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionFile); - - Action action = () => - { - SlnFile.Read(tmpFile); - }; - - action.Should().Throw() - .WithMessage(FormatError(4, LocalizableStrings.SectionIdMissingError)); - } - - [Fact] - public void WhenGivenASolutionWithSectionNotClosedItThrows() - { - const string SolutionFile = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution -EndGlobal -"; - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionFile); - - Action action = () => - { - SlnFile.Read(tmpFile); - }; - - action.Should().Throw() - .WithMessage(FormatError(6, LocalizableStrings.ClosingSectionTagNotFoundError)); - } - - [Fact] - public void WhenGivenASolutionWithInvalidPropertySetItThrows() - { - const string SolutionFile = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -Project(""{7072A694-548F-4CAE-A58F-12D257D5F486}"") = ""AppModified"", ""AppModified\AppModified.csproj"", ""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"" -EndProject -Global - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7072A694-548F-4CAE-A58F-12D257D5F486} Debug|Any CPU ActiveCfg = Debug|Any CPU - EndGlobalSection -EndGlobal -"; - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionFile); - - Action action = () => - { - var slnFile = SlnFile.Read(tmpFile); - if (slnFile.ProjectConfigurationsSection.Count == 0) - { - // Need to force loading of nested property sets - } - }; - - action.Should().Throw() - .WithMessage(FormatError(7, LocalizableStrings.InvalidPropertySetFormatString, ".")); - } - - private static string FormatError(int line, string format, params object[] args) - { - return string.Format( - LocalizableStrings.ErrorMessageFormatString, - line, - string.Format(format, args)); - } - } -} diff --git a/test/Microsoft.DotNet.Cli.Sln.Internal.Tests/Microsoft.DotNet.Cli.Sln.Internal.Tests.csproj b/test/Microsoft.DotNet.Cli.Sln.Internal.Tests/Microsoft.DotNet.Cli.Sln.Internal.Tests.csproj deleted file mode 100644 index 1c9566e18687..000000000000 --- a/test/Microsoft.DotNet.Cli.Sln.Internal.Tests/Microsoft.DotNet.Cli.Sln.Internal.Tests.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - Tests\$(MSBuildProjectName) - - - - - - $(ToolsetTargetFramework) - Exe - MicrosoftAspNetCore - - - - - - - - - - diff --git a/test/Microsoft.DotNet.GenAPI.Tests/CSharpFileBuilderTests.cs b/test/Microsoft.DotNet.GenAPI.Tests/CSharpFileBuilderTests.cs index 81856d2842ce..c53d1445cef1 100644 --- a/test/Microsoft.DotNet.GenAPI.Tests/CSharpFileBuilderTests.cs +++ b/test/Microsoft.DotNet.GenAPI.Tests/CSharpFileBuilderTests.cs @@ -9,7 +9,6 @@ using Microsoft.DotNet.ApiSymbolExtensions; using Microsoft.DotNet.ApiSymbolExtensions.Filtering; using Microsoft.DotNet.ApiSymbolExtensions.Logging; -using Microsoft.DotNet.ApiSymbolExtensions.Tests; using Moq; namespace Microsoft.DotNet.GenAPI.Tests @@ -32,47 +31,32 @@ private void RunTest(string original, bool includeEffectivelyPrivateSymbols = true, bool includeExplicitInterfaceImplementationSymbols = true, bool allowUnsafe = false, - string excludedAttributeFile = null, + string[] excludedAttributeList = null, [CallerMemberName] string assemblyName = "") { - StringWriter stringWriter = new(); + using StringWriter stringWriter = new(); - // Configure symbol filters - AccessibilitySymbolFilter accessibilitySymbolFilter = new( - includeInternalSymbols, - includeEffectivelyPrivateSymbols, - includeExplicitInterfaceImplementationSymbols); - - CompositeSymbolFilter symbolFilter = new CompositeSymbolFilter() - .Add(new ImplicitSymbolFilter()) - .Add(accessibilitySymbolFilter); + Mock log = new(); - CompositeSymbolFilter attributeDataSymbolFilter = new(); - if (excludedAttributeFile is not null) - { - attributeDataSymbolFilter.Add(new DocIdSymbolFilter(new string[] { excludedAttributeFile })); - } - attributeDataSymbolFilter.Add(accessibilitySymbolFilter); + (IAssemblySymbolLoader loader, Dictionary assemblySymbols) = TestAssemblyLoaderFactory + .CreateFromTexts(log.Object, assemblyTexts: [(assemblyName, original)], respectInternals: includeInternalSymbols, allowUnsafe: allowUnsafe); - Mock log = new(); + ISymbolFilter symbolFilter = SymbolFilterFactory.GetFilterFromList([], null, includeInternalSymbols, includeEffectivelyPrivateSymbols, includeExplicitInterfaceImplementationSymbols); + ISymbolFilter attributeDataSymbolFilter = SymbolFilterFactory.GetFilterFromList(excludedAttributeList, null, includeInternalSymbols, includeEffectivelyPrivateSymbols, includeExplicitInterfaceImplementationSymbols); IAssemblySymbolWriter csharpFileBuilder = new CSharpFileBuilder( log.Object, + stringWriter, + loader, symbolFilter, attributeDataSymbolFilter, - stringWriter, - null, - false, + header: string.Empty, + exceptionMessage: null, + includeAssemblyAttributes: false, MetadataReferences, addPartialModifier: true); - using Stream assemblyStream = SymbolFactory.EmitAssemblyStreamFromSyntax(original, enableNullable: true, allowUnsafe: allowUnsafe, assemblyName: assemblyName); - AssemblySymbolLoader assemblySymbolLoader = new(log.Object, resolveAssemblyReferences: true, includeInternalSymbols: includeInternalSymbols); - assemblySymbolLoader.AddReferenceSearchPaths(typeof(object).Assembly!.Location!); - assemblySymbolLoader.AddReferenceSearchPaths(typeof(DynamicAttribute).Assembly!.Location!); - IAssemblySymbol assemblySymbol = assemblySymbolLoader.LoadAssembly(assemblyName, assemblyStream); - - csharpFileBuilder.WriteAssembly(assemblySymbol); + csharpFileBuilder.WriteAssembly(assemblySymbols.First().Value); StringBuilder stringBuilder = stringWriter.GetStringBuilder(); string resultedString = stringBuilder.ToString(); @@ -2764,10 +2748,6 @@ public class PublicClass { } [Fact] public void TestAttributesExcludedWithFilter() { - using TempDirectory root = new(); - string filePath = Path.Combine(root.DirPath, "exclusions.txt"); - File.WriteAllText(filePath, "T:A.AnyTestAttribute"); - RunTest(original: """ namespace A { @@ -2803,7 +2783,7 @@ public partial class PublicClass } """, includeInternalSymbols: false, - excludedAttributeFile: filePath); + excludedAttributeList: ["T:A.AnyTestAttribute"]); } [Fact] diff --git a/test/Microsoft.DotNet.GenAPI.Tests/TestAssemblyLoaderFactory.cs b/test/Microsoft.DotNet.GenAPI.Tests/TestAssemblyLoaderFactory.cs new file mode 100644 index 000000000000..9bd062acf33a --- /dev/null +++ b/test/Microsoft.DotNet.GenAPI.Tests/TestAssemblyLoaderFactory.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; +using Microsoft.CodeAnalysis; +using Microsoft.DotNet.ApiSymbolExtensions; +using Microsoft.DotNet.ApiSymbolExtensions.Logging; +using Microsoft.DotNet.ApiSymbolExtensions.Tests; + +namespace Microsoft.DotNet.GenAPI.Tests; + +public class TestAssemblyLoaderFactory +{ + public static (IAssemblySymbolLoader, Dictionary) CreateFromTexts(ILog log, (string, string)[] assemblyTexts, IEnumerable>? diagnosticOptions = null, bool respectInternals = false, bool allowUnsafe = false) + { + if (assemblyTexts.Length == 0) + { + return (new AssemblySymbolLoader(log, diagnosticOptions, resolveAssemblyReferences: true, includeInternalSymbols: respectInternals), + new Dictionary()); + } + + AssemblySymbolLoader loader = new(log, diagnosticOptions, resolveAssemblyReferences: true, includeInternalSymbols: respectInternals); + loader.AddReferenceSearchPaths(typeof(object).Assembly!.Location!); + loader.AddReferenceSearchPaths(typeof(DynamicAttribute).Assembly!.Location!); + + Dictionary assemblySymbols = new(); + foreach ((string assemblyName, string assemblyText) in assemblyTexts) + { + using Stream assemblyStream = SymbolFactory.EmitAssemblyStreamFromSyntax(assemblyText, diagnosticOptions, enableNullable: true, allowUnsafe: allowUnsafe, assemblyName: assemblyName); + if (loader.LoadAssembly(assemblyName, assemblyStream) is IAssemblySymbol assemblySymbol) + { + assemblySymbols.Add(assemblyName, assemblySymbol); + } + } + + return (loader, assemblySymbols); + } +} diff --git a/test/Microsoft.DotNet.MSBuildSdkResolver.Tests/Microsoft.DotNet.MSBuildSdkResolver.Tests.csproj b/test/Microsoft.DotNet.MSBuildSdkResolver.Tests/Microsoft.DotNet.MSBuildSdkResolver.Tests.csproj index 6d825c7ed719..3928da4a73cc 100644 --- a/test/Microsoft.DotNet.MSBuildSdkResolver.Tests/Microsoft.DotNet.MSBuildSdkResolver.Tests.csproj +++ b/test/Microsoft.DotNet.MSBuildSdkResolver.Tests/Microsoft.DotNet.MSBuildSdkResolver.Tests.csproj @@ -8,6 +8,10 @@ net472 + + true MicrosoftAspNetCore + $(ToolsetTargetFramework) Exe MicrosoftAspNetCore diff --git a/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/HotReloadAgentTest.cs b/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/HotReloadAgentTest.cs index 3c0673244bed..ce3644bd4e6a 100644 --- a/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/HotReloadAgentTest.cs +++ b/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/HotReloadAgentTest.cs @@ -9,6 +9,29 @@ namespace Microsoft.DotNet.Watch.UnitTests { public class HotReloadAgentTest { + [Fact] + public void ClearHotReloadEnvironmentVariables_ClearsStartupHook() + { + Assert.Equal("", + HotReloadAgent.RemoveCurrentAssembly(typeof(StartupHook), typeof(StartupHook).Assembly.Location)); + } + + [Fact] + public void ClearHotReloadEnvironmentVariables_PreservedOtherStartupHooks() + { + var customStartupHook = "/path/mycoolstartup.dll"; + Assert.Equal(customStartupHook, + HotReloadAgent.RemoveCurrentAssembly(typeof(StartupHook), typeof(StartupHook).Assembly.Location + Path.PathSeparator + customStartupHook)); + } + + [PlatformSpecificFact(TestPlatforms.Windows)] + public void ClearHotReloadEnvironmentVariables_RemovesHotReloadStartup_InCaseInvariantManner() + { + var customStartupHook = "/path/mycoolstartup.dll"; + Assert.Equal(customStartupHook, + HotReloadAgent.RemoveCurrentAssembly(typeof(StartupHook), customStartupHook + Path.PathSeparator + typeof(StartupHook).Assembly.Location.ToUpperInvariant())); + } + [Fact] public void TopologicalSort_Works() { @@ -55,40 +78,49 @@ public void TopologicalSort_WithCycles() Assert.Equal(new[] { assembly1, assembly3, assembly2, assembly4, assembly5 }, sortedList); } - [Fact] - public void GetHandlerActions_DiscoversActionsOnTypeWithClearCache() + [Theory] + [InlineData(typeof(HandlerWithClearCache))] + [InlineData(typeof(HandlerWithUpdateApplication))] + [InlineData(typeof(HandlerWithUpdateContent))] + public void GetHandlerActions_SingleAction(Type handlerType) { var reporter = new AgentReporter(); var invoker = new MetadataUpdateHandlerInvoker(reporter); - var actions = invoker.GetMetadataUpdateHandlerActions([typeof(HandlerWithClearCache)]); + var actions = invoker.GetUpdateHandlerActions([handlerType]); Assert.Empty(reporter.GetAndClearLogEntries(ResponseLoggingLevel.Verbose)); - Assert.Single(actions.ClearCache); - Assert.Empty(actions.UpdateApplication); - } - [Fact] - public void GetHandlerActions_DiscoversActionsOnTypeWithUpdateApplication() - { - var reporter = new AgentReporter(); - var invoker = new MetadataUpdateHandlerInvoker(reporter); - var actions = invoker.GetMetadataUpdateHandlerActions([typeof(HandlerWithUpdateApplication)]); - - Assert.Empty(reporter.GetAndClearLogEntries(ResponseLoggingLevel.Verbose)); - Assert.Empty(actions.ClearCache); - Assert.Single(actions.UpdateApplication); + if (handlerType == typeof(HandlerWithUpdateContent)) + { + Assert.Single(actions.UpdateContentHandlers); + Assert.Empty(actions.ClearCacheHandlers); + Assert.Empty(actions.UpdateApplicationHandlers); + } + else if (handlerType == typeof(HandlerWithUpdateApplication)) + { + Assert.Single(actions.UpdateApplicationHandlers); + Assert.Empty(actions.ClearCacheHandlers); + Assert.Empty(actions.UpdateContentHandlers); + } + else if (handlerType == typeof(HandlerWithClearCache)) + { + Assert.Single(actions.ClearCacheHandlers); + Assert.Empty(actions.UpdateContentHandlers); + Assert.Empty(actions.UpdateApplicationHandlers); + } } [Fact] - public void GetHandlerActions_DiscoversActionsOnTypeWithBothActions() + public void GetHandlerActions_DiscoversActionsOnTypeWithAllActions() { var reporter = new AgentReporter(); var invoker = new MetadataUpdateHandlerInvoker(reporter); - var actions = invoker.GetMetadataUpdateHandlerActions([typeof(HandlerWithBothActions)]); + var actions = invoker.GetUpdateHandlerActions([typeof(HandlerWithAllActions)]); - Assert.Empty(reporter.GetAndClearLogEntries(ResponseLoggingLevel.Verbose)); - Assert.Single(actions.ClearCache); - Assert.Single(actions.UpdateApplication); + AssertEx.Empty(reporter.GetAndClearLogEntries(ResponseLoggingLevel.Verbose)); + Assert.Equal(typeof(HandlerWithAllActions).GetMethod("ClearCache", BindingFlags.Static | BindingFlags.NonPublic), actions.ClearCacheHandlers.Single().Method); + Assert.Equal(typeof(HandlerWithAllActions).GetMethod("UpdateApplication", BindingFlags.Static | BindingFlags.NonPublic), actions.UpdateApplicationHandlers.Single().Method); + Assert.Equal(typeof(HandlerWithAllActions).GetMethod("UpdateContent", BindingFlags.Static | BindingFlags.NonPublic), actions.UpdateContentHandlers.Single().Method); } [Fact] @@ -98,14 +130,19 @@ public void GetHandlerActions_LogsMessageIfMethodHasIncorrectSignature() var invoker = new MetadataUpdateHandlerInvoker(reporter); var handlerType = typeof(HandlerWithIncorrectSignature); - var actions = invoker.GetMetadataUpdateHandlerActions([handlerType]); + var actions = invoker.GetUpdateHandlerActions([handlerType]); var log = reporter.GetAndClearLogEntries(ResponseLoggingLevel.WarningsAndErrors); - var logEntry = Assert.Single(log); - Assert.Equal($"Type '{handlerType}' has method 'Void ClearCache()' that does not match the required signature.", logEntry.message); - Assert.Equal(AgentMessageSeverity.Warning, logEntry.severity); - Assert.Empty(actions.ClearCache); - Assert.Single(actions.UpdateApplication); + AssertEx.SequenceEqual( + [ + $"Warning: Type '{handlerType}' has method 'Void ClearCache()' that does not match the required signature.", + $"Warning: Type '{handlerType}' has method 'Void UpdateContent()' that does not match the required signature." + ], + log.Select(e => $"{e.severity}: {e.message}")); + + Assert.Empty(actions.ClearCacheHandlers); + Assert.Empty(actions.UpdateContentHandlers); + Assert.Single(actions.UpdateApplicationHandlers); } [Fact] @@ -115,16 +152,16 @@ public void GetHandlerActions_LogsMessageIfNoActionsAreDiscovered() var invoker = new MetadataUpdateHandlerInvoker(reporter); var handlerType = typeof(HandlerWithNoActions); - var actions = invoker.GetMetadataUpdateHandlerActions([handlerType]); + var actions = invoker.GetUpdateHandlerActions([handlerType]); var log = reporter.GetAndClearLogEntries(ResponseLoggingLevel.WarningsAndErrors); var logEntry = Assert.Single(log); Assert.Equal( - $"Expected to find a static method 'ClearCache' or 'UpdateApplication' on type '{handlerType.AssemblyQualifiedName}' but neither exists.", logEntry.message); + $"Expected to find a static method 'ClearCache', 'UpdateApplication' or 'UpdateContent' on type '{handlerType.AssemblyQualifiedName}' but neither exists.", logEntry.message); Assert.Equal(AgentMessageSeverity.Warning, logEntry.severity); - Assert.Empty(actions.ClearCache); - Assert.Empty(actions.UpdateApplication); + Assert.Empty(actions.ClearCacheHandlers); + Assert.Empty(actions.UpdateApplicationHandlers); } private static Assembly GetAssembly(string fullName, AssemblyName[] dependencies) @@ -147,15 +184,22 @@ private class HandlerWithUpdateApplication internal static void UpdateApplication(Type[]? _) { } } - private class HandlerWithBothActions + private class HandlerWithUpdateContent + { + public static void UpdateContent(string assemblyName, bool isApplicationProject, string relativePath, byte[] contents) { } + } + + private class HandlerWithAllActions { internal static void ClearCache(Type[]? _) { } internal static void UpdateApplication(Type[]? _) { } + internal static void UpdateContent(string assemblyName, bool isApplicationProject, string relativePath, byte[] contents) { } } private class HandlerWithIncorrectSignature { - internal static void ClearCache() { } + internal static void ClearCache() { } + internal static void UpdateContent() { } internal static void UpdateApplication(Type[]? _) { } } diff --git a/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/UpdatePayloadTests.cs b/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/ManagedCodeUpdateRequestTests.cs similarity index 83% rename from test/Microsoft.Extensions.DotNetDeltaApplier.Tests/UpdatePayloadTests.cs rename to test/Microsoft.Extensions.DotNetDeltaApplier.Tests/ManagedCodeUpdateRequestTests.cs index 79b2240033c9..f053a48ac90f 100644 --- a/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/UpdatePayloadTests.cs +++ b/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/ManagedCodeUpdateRequestTests.cs @@ -5,12 +5,12 @@ namespace Microsoft.DotNet.Watch.UnitTests; -public class UpdatePayloadTests +public class ManagedCodeUpdateRequestTests { [Fact] public async Task Roundtrip() { - var initial = new UpdatePayload( + var initial = new ManagedCodeUpdateRequest( [ new UpdateDelta( moduleId: Guid.NewGuid(), @@ -31,7 +31,7 @@ public async Task Roundtrip() await initial.WriteAsync(stream, CancellationToken.None); stream.Position = 0; - var read = await UpdatePayload.ReadAsync(stream, CancellationToken.None); + var read = await ManagedCodeUpdateRequest.ReadAsync(stream, CancellationToken.None); AssertEqual(initial, read); } @@ -39,7 +39,7 @@ public async Task Roundtrip() [Fact] public async Task WithLargeDeltas() { - var initial = new UpdatePayload( + var initial = new ManagedCodeUpdateRequest( [ new UpdateDelta( moduleId: Guid.NewGuid(), @@ -54,12 +54,12 @@ public async Task WithLargeDeltas() await initial.WriteAsync(stream, CancellationToken.None); stream.Position = 0; - var read = await UpdatePayload.ReadAsync(stream, CancellationToken.None); + var read = await ManagedCodeUpdateRequest.ReadAsync(stream, CancellationToken.None); AssertEqual(initial, read); } - private static void AssertEqual(UpdatePayload initial, UpdatePayload read) + private static void AssertEqual(ManagedCodeUpdateRequest initial, ManagedCodeUpdateRequest read) { Assert.Equal(initial.Deltas.Count, read.Deltas.Count); diff --git a/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/Microsoft.Extensions.DotNetDeltaApplier.Tests.csproj b/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/Microsoft.Extensions.DotNetDeltaApplier.Tests.csproj index 80f7bb4f2a2b..1d8dddb75f81 100644 --- a/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/Microsoft.Extensions.DotNetDeltaApplier.Tests.csproj +++ b/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/Microsoft.Extensions.DotNetDeltaApplier.Tests.csproj @@ -7,6 +7,10 @@ Exe + + + + diff --git a/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/StartupHookTests.cs b/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/StartupHookTests.cs index 547f0618f049..6914eeb525a9 100644 --- a/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/StartupHookTests.cs +++ b/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/StartupHookTests.cs @@ -1,30 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.DotNet.HotReload; + namespace Microsoft.DotNet.Watch.UnitTests { public class StartupHookTests { - [Fact] - public void ClearHotReloadEnvironmentVariables_ClearsStartupHook() - { - Assert.Equal("", StartupHook.RemoveCurrentAssembly(typeof(StartupHook).Assembly.Location)); - } - - [Fact] - public void ClearHotReloadEnvironmentVariables_PreservedOtherStartupHooks() - { - var customStartupHook = "/path/mycoolstartup.dll"; - Assert.Equal(customStartupHook, StartupHook.RemoveCurrentAssembly(typeof(StartupHook).Assembly.Location + Path.PathSeparator + customStartupHook)); - } - - [Fact] - public void ClearHotReloadEnvironmentVariables_RemovesHotReloadStartup_InCaseInvariantManner() - { - var customStartupHook = "/path/mycoolstartup.dll"; - Assert.Equal(customStartupHook, StartupHook.RemoveCurrentAssembly(customStartupHook + Path.PathSeparator + typeof(StartupHook).Assembly.Location.ToUpperInvariant())); - } - [Theory] [CombinatorialData] public void IsMatchingProcess_Matching_SimpleName( diff --git a/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/StaticAssetPayloadTests.cs b/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/StaticAssetUpdateRequestTests.cs similarity index 67% rename from test/Microsoft.Extensions.DotNetDeltaApplier.Tests/StaticAssetPayloadTests.cs rename to test/Microsoft.Extensions.DotNetDeltaApplier.Tests/StaticAssetUpdateRequestTests.cs index 1240d15b7fb0..4486270c472b 100644 --- a/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/StaticAssetPayloadTests.cs +++ b/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/StaticAssetUpdateRequestTests.cs @@ -5,27 +5,28 @@ namespace Microsoft.DotNet.Watch.UnitTests; -public class StaticAssetPayloadTests +public class StaticAssetUpdateRequestTests { [Fact] public async Task Roundtrip() { - var initial = new StaticAssetPayload( + var initial = new StaticAssetUpdateRequest( assemblyName: "assembly name", relativePath: "some path", [1, 2, 3], - isApplicationProject: true); + isApplicationProject: true, + responseLoggingLevel: ResponseLoggingLevel.WarningsAndErrors); using var stream = new MemoryStream(); await initial.WriteAsync(stream, CancellationToken.None); stream.Position = 0; - var read = await StaticAssetPayload.ReadAsync(stream, CancellationToken.None); + var read = await StaticAssetUpdateRequest.ReadAsync(stream, CancellationToken.None); AssertEqual(initial, read); } - private static void AssertEqual(StaticAssetPayload initial, StaticAssetPayload read) + private static void AssertEqual(StaticAssetUpdateRequest initial, StaticAssetUpdateRequest read) { Assert.Equal(initial.AssemblyName, read.AssemblyName); Assert.Equal(initial.RelativePath, read.RelativePath); diff --git a/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/StreamExtensionsTests.cs b/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/StreamExtensionsTests.cs index 2da1c3b4252d..73996d5019f0 100644 --- a/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/StreamExtensionsTests.cs +++ b/test/Microsoft.Extensions.DotNetDeltaApplier.Tests/StreamExtensionsTests.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.DotNet.HotReload; + namespace Microsoft.DotNet.Watch.UnitTests; public class StreamExtensionsTests diff --git a/test/Microsoft.NET.Build.Containers.IntegrationTests/CreateNewImageTests.cs b/test/Microsoft.NET.Build.Containers.IntegrationTests/CreateNewImageTests.cs index e1a8055cd158..b00de74ceaa0 100644 --- a/test/Microsoft.NET.Build.Containers.IntegrationTests/CreateNewImageTests.cs +++ b/test/Microsoft.NET.Build.Containers.IntegrationTests/CreateNewImageTests.cs @@ -298,6 +298,72 @@ public async System.Threading.Tasks.Task CreateNewImage_RootlessBaseImage() Assert.Equal(RootlessUser, imageBuilder.BaseImageConfig.GetUser()); } + + [DockerAvailableFact] + public void CanOverrideContainerImageFormat() + { + DirectoryInfo newProjectDir = new(GetTestDirectoryName()); + + if (newProjectDir.Exists) + { + newProjectDir.Delete(recursive: true); + } + + newProjectDir.Create(); + + new DotnetNewCommand(_testOutput, "console", "-f", ToolsetInfo.CurrentTargetFramework) + .WithVirtualHive() + .WithWorkingDirectory(newProjectDir.FullName) + .Execute() + .Should().Pass(); + + new DotnetCommand(_testOutput, "build", "--configuration", "release") + .WithWorkingDirectory(newProjectDir.FullName) + .Execute() + .Should().Pass(); + + ParseContainerProperties pcp = new(); + (IBuildEngine buildEngine, List errors) = SetupBuildEngine(); + pcp.BuildEngine = buildEngine; + + pcp.FullyQualifiedBaseImageName = "mcr.microsoft.com/dotnet/runtime:9.0"; + pcp.ContainerRegistry = "localhost:5010"; + pcp.ContainerRepository = "dotnet/testimage"; + pcp.ContainerImageTags = new[] { "5.0", "latest" }; + + Assert.True(pcp.Execute(), FormatBuildMessages(errors)); + Assert.Equal("mcr.microsoft.com", pcp.ParsedContainerRegistry); + Assert.Equal("dotnet/runtime", pcp.ParsedContainerImage); + Assert.Equal("9.0", pcp.ParsedContainerTag); + + Assert.Equal("dotnet/testimage", pcp.NewContainerRepository); + pcp.NewContainerTags.Should().BeEquivalentTo(new[] { "5.0", "latest" }); + + CreateNewImage cni = new(); + (buildEngine, errors) = SetupBuildEngine(); + cni.BuildEngine = buildEngine; + + cni.BaseRegistry = pcp.ParsedContainerRegistry; + cni.BaseImageName = pcp.ParsedContainerImage; + cni.BaseImageTag = pcp.ParsedContainerTag; + cni.Repository = pcp.NewContainerRepository; + cni.OutputRegistry = "localhost:5010"; + cni.PublishDirectory = Path.Combine(newProjectDir.FullName, "bin", "release", ToolsetInfo.CurrentTargetFramework); + cni.WorkingDirectory = "app/"; + cni.Entrypoint = new TaskItem[] { new(newProjectDir.Name) }; + cni.ImageTags = pcp.NewContainerTags; + cni.ContainerRuntimeIdentifier = "linux-x64"; + cni.RuntimeIdentifierGraphPath = ToolsetUtils.GetRuntimeGraphFilePath(); + + cni.ImageFormat = KnownImageFormats.OCI.ToString(); + + Assert.True(cni.Execute(), FormatBuildMessages(errors)); + + cni.GeneratedContainerMediaType.Should().Be(SchemaTypes.OciManifestV1); + newProjectDir.Delete(true); + } + + private static (IBuildEngine buildEngine, List errors) SetupBuildEngine() { List errors = new(); diff --git a/test/Microsoft.NET.Build.Containers.IntegrationTests/EndToEndTests.cs b/test/Microsoft.NET.Build.Containers.IntegrationTests/EndToEndTests.cs index f38433e3fcda..6cbbdd87c9fc 100644 --- a/test/Microsoft.NET.Build.Containers.IntegrationTests/EndToEndTests.cs +++ b/test/Microsoft.NET.Build.Containers.IntegrationTests/EndToEndTests.cs @@ -194,7 +194,7 @@ public async Task ApiEndToEndWithArchiveWritingAndLoad() [DockerAvailableFact] public async Task TarballsHaveCorrectStructure() - { + { var archiveFile = Path.Combine(TestSettings.TestArtifactsDirectory, nameof(TarballsHaveCorrectStructure), "app.tar.gz"); @@ -203,7 +203,7 @@ public async Task TarballsHaveCorrectStructure() await BuildDockerImageWithArciveDestinationAsync(archiveFile, ["latest"], nameof(TarballsHaveCorrectStructure)); await destinationReference.LocalRegistry!.LoadAsync(dockerImage, sourceReference, destinationReference, default).ConfigureAwait(false); - + Assert.True(File.Exists(archiveFile), $"File.Exists({archiveFile})"); CheckDockerTarballStructure(archiveFile); @@ -659,7 +659,7 @@ public void EndToEnd_NoAPI_Console(string baseImage) .Should().Pass(); // Add package to the project - new DotnetCommand(_testOutput, "add", "package", "Microsoft.NET.Build.Containers", "-f", _oldFramework , "-v", packageVersion ?? string.Empty) + new DotnetCommand(_testOutput, "add", "package", "Microsoft.NET.Build.Containers", "-f", _oldFramework, "-v", packageVersion ?? string.Empty) .WithEnvironmentVariable("NUGET_PACKAGES", privateNuGetAssets.FullName) .WithWorkingDirectory(newProjectDir.FullName) .Execute() @@ -702,6 +702,39 @@ public void EndToEnd_NoAPI_Console(string baseImage) privateNuGetAssets.Delete(true); } + [DockerAvailableFact(Skip = "https://github.com/dotnet/sdk/issues/45181")] + public void EndToEnd_SingleArch_NoRid() + { + // Create a new console project + DirectoryInfo newProjectDir = CreateNewProject("console", _oldFramework); + + string imageName = NewImageName(); + string imageTag = "1.0"; + + // Run PublishContainer for multi-arch + CommandResult commandResult = new DotnetCommand( + _testOutput, + "publish", + "/t:PublishContainer", + $"/p:ContainerBaseImage={DockerRegistryManager.FullyQualifiedBaseImageAspNet}", + $"/p:ContainerRepository={imageName}", + $"/p:ContainerImageTag={imageTag}", + "/p:EnableSdkContainerSupport=true") + .WithWorkingDirectory(newProjectDir.FullName) + .Execute(); + commandResult.Should().Pass(); + + // Check that the containers can be run + CommandResult processResultX64 = ContainerCli.RunCommand( + _testOutput, + "--rm", + "--name", + $"test-container-singlearch-norid", + $"{imageName}:{imageTag}") + .Execute(); + processResultX64.Should().Pass().And.HaveStdOut("Hello, World!"); + } + [DockerIsAvailableAndSupportsArchFact("linux/arm64")] public void EndToEndMultiArch_LocalRegistry() { @@ -711,7 +744,7 @@ public void EndToEndMultiArch_LocalRegistry() string imageArm64 = $"{imageName}:{imageTag}-linux-arm64"; // Create a new console project - DirectoryInfo newProjectDir = CreateNewProject("console"); + DirectoryInfo newProjectDir = CreateNewProject("console", _oldFramework); // Run PublishContainer for multi-arch CommandResult commandResult = new DotnetCommand( @@ -730,8 +763,8 @@ public void EndToEndMultiArch_LocalRegistry() // images were created locally for each RID // and image index was NOT created commandResult.Should().Pass() - .And.HaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, "linux-x64")) - .And.HaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, "linux-arm64")) + .And.HaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, _oldFramework, "linux-x64")) + .And.HaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, _oldFramework, "linux-arm64")) .And.HaveStdOutContaining($"Pushed image '{imageX64}' to local registry") .And.HaveStdOutContaining($"Pushed image '{imageArm64}' to local registry") .And.NotHaveStdOutContaining("Pushed image index"); @@ -759,7 +792,109 @@ public void EndToEndMultiArch_LocalRegistry() newProjectDir.Delete(true); } - private DirectoryInfo CreateNewProject(string template, [CallerMemberName] string callerMemberName = "") + [DockerAvailableFact(Skip = "https://github.com/dotnet/sdk/issues/45181")] + public void MultiArchStillAllowsSingleRID() + { + string imageName = NewImageName(); + string imageTag = "1.0"; + string qualifiedImageName = $"{imageName}:{imageTag}"; + + // Create a new console project + DirectoryInfo newProjectDir = CreateNewProject("console", _oldFramework); + + // Run PublishContainer for multi-arch-capable, but single-arch actual + CommandResult commandResult = new DotnetCommand( + _testOutput, + "publish", + "/t:PublishContainer", + // make it so the app is _able_ to target both linux TFMs + "/p:RuntimeIdentifiers=\"linux-x64;linux-arm64\"", + // and that it opts into to multi-targeting containers for both of those linux TFMs + "/p:ContainerRuntimeIdentifiers=\"linux-x64;linux-arm64\"", + // but then only actually publishes for one of them + "/p:ContainerRuntimeIdentifier=linux-x64", + $"/p:ContainerBaseImage={DockerRegistryManager.FullyQualifiedBaseImageAspNet}", + $"/p:ContainerRepository={imageName}", + $"/p:ContainerImageTag={imageTag}", + "/p:EnableSdkContainerSupport=true", + "/bl") + .WithWorkingDirectory(newProjectDir.FullName) + .Execute(); + + // Check that the app was published for each RID, + // images were created locally for each RID + // and image index was NOT created + commandResult.Should().Pass() + // no rid-specific path because we didn't pass RuntimeIdentifier + .And.NotHaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, _oldFramework, "linux-x64")) + .And.HaveStdOutContaining($"Pushed image '{qualifiedImageName}' to local registry") + .And.NotHaveStdOutContaining("Pushed image index"); + + // Check that the containers can be run + CommandResult processResultX64 = ContainerCli.RunCommand( + _testOutput, + "--rm", + "--name", + $"test-container-{imageName}", + qualifiedImageName) + .Execute(); + processResultX64.Should().Pass().And.HaveStdOut("Hello, World!"); + + // Cleanup + newProjectDir.Delete(true); + } + + [DockerAvailableFact(Skip = "https://github.com/dotnet/sdk/issues/45181")] + public void MultiArchStillAllowsSingleRIDUsingJustRIDProperties() + { + string imageName = NewImageName(); + string imageTag = "1.0"; + string qualifiedImageName = $"{imageName}:{imageTag}"; + + // Create a new console project + DirectoryInfo newProjectDir = CreateNewProject("console", _oldFramework); + + // Run PublishContainer for multi-arch-capable, but single-arch actual + CommandResult commandResult = new DotnetCommand( + _testOutput, + "publish", + "/t:PublishContainer", + // make it so the app is _able_ to target both linux TFMs + "/p:RuntimeIdentifiers=\"linux-x64;linux-arm64\"", + // but then only actually publishes for one of them + "-r", "linux-x64", + $"/p:ContainerBaseImage={DockerRegistryManager.FullyQualifiedBaseImageAspNet}", + $"/p:ContainerRepository={imageName}", + $"/p:ContainerImageTag={imageTag}", + "/p:EnableSdkContainerSupport=true", + "/bl") + .WithWorkingDirectory(newProjectDir.FullName) + .Execute(); + + // Check that the app was published for each RID, + // images were created locally for each RID + // and image index was NOT created + commandResult.Should().Pass() + .And.HaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, _oldFramework, "linux-x64", configuration: "Release")) + .And.NotHaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, _oldFramework, "linux-arm64", configuration: "Release")) + .And.HaveStdOutContaining($"Pushed image '{qualifiedImageName}' to local registry") + .And.NotHaveStdOutContaining("Pushed image index"); + + // Check that the containers can be run + CommandResult processResultX64 = ContainerCli.RunCommand( + _testOutput, + "--rm", + "--name", + $"test-container-{imageName}-x64", + qualifiedImageName) + .Execute(); + processResultX64.Should().Pass().And.HaveStdOut("Hello, World!"); + + // Cleanup + newProjectDir.Delete(true); + } + + private DirectoryInfo CreateNewProject(string template, string tfm = ToolsetInfo.CurrentTargetFramework, [CallerMemberName] string callerMemberName = "") { DirectoryInfo newProjectDir = new DirectoryInfo(Path.Combine(TestSettings.TestArtifactsDirectory, callerMemberName)); @@ -770,7 +905,7 @@ private DirectoryInfo CreateNewProject(string template, [CallerMemberName] strin newProjectDir.Create(); - new DotnetNewCommand(_testOutput, template, "-f", ToolsetInfo.CurrentTargetFramework) + new DotnetNewCommand(_testOutput, template, "-f", tfm) .WithVirtualHive() .WithWorkingDirectory(newProjectDir.FullName) .Execute() @@ -779,8 +914,8 @@ private DirectoryInfo CreateNewProject(string template, [CallerMemberName] strin return newProjectDir; } - private string GetPublishArtifactsPath(string projectDir, string rid) - => Path.Combine(projectDir, "bin", "Debug", ToolsetInfo.CurrentTargetFramework, rid, "publish"); + private string GetPublishArtifactsPath(string projectDir, string tfm, string rid, string configuration = "Debug") + => Path.Combine(projectDir, "bin", configuration, tfm, rid, "publish"); [DockerIsAvailableAndSupportsArchFact("linux/arm64")] public void EndToEndMultiArch_ArchivePublishing() @@ -794,7 +929,7 @@ public void EndToEndMultiArch_ArchivePublishing() string imageArm64Tarball = Path.Combine(archiveOutput, $"{imageName}-linux-arm64.tar.gz"); // Create a new console project - DirectoryInfo newProjectDir = CreateNewProject("console"); + DirectoryInfo newProjectDir = CreateNewProject("console", _oldFramework); // Run PublishContainer for multi-arch with ContainerArchiveOutputPath CommandResult commandResult = new DotnetCommand( @@ -814,14 +949,14 @@ public void EndToEndMultiArch_ArchivePublishing() // images were created locally for each RID // and image index was NOT created commandResult.Should().Pass() - .And.HaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, "linux-x64")) - .And.HaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, "linux-arm64")) + .And.HaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, _oldFramework, "linux-x64")) + .And.HaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, _oldFramework, "linux-arm64")) .And.HaveStdOutContaining($"Pushed image '{imageX64}' to local archive at '{imageX64Tarball}'") .And.HaveStdOutContaining($"Pushed image '{imageArm64}' to local archive at '{imageArm64Tarball}'") .And.NotHaveStdOutContaining("Pushed image index"); - // Check that tarballs were created - File.Exists(imageX64Tarball).Should().BeTrue(); + // Check that tarballs were created + File.Exists(imageX64Tarball).Should().BeTrue(); File.Exists(imageArm64Tarball).Should().BeTrue(); // Load the images from the tarballs @@ -866,8 +1001,8 @@ public void EndToEndMultiArch_RemoteRegistry() string imageIndex = $"{imageName}:{imageTag}"; // Create a new console project - DirectoryInfo newProjectDir = CreateNewProject("console"); - + DirectoryInfo newProjectDir = CreateNewProject("console", _oldFramework); + // Run PublishContainer for multi-arch with ContainerRegistry CommandResult commandResult = new DotnetCommand( _testOutput, @@ -886,8 +1021,8 @@ public void EndToEndMultiArch_RemoteRegistry() // images were created locally for each RID // and image index was created commandResult.Should().Pass() - .And.HaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, "linux-x64")) - .And.HaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, "linux-arm64")) + .And.HaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, _oldFramework, "linux-x64")) + .And.HaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, _oldFramework, "linux-arm64")) .And.HaveStdOutContaining($"Pushed image '{imageX64}' to registry") .And.HaveStdOutContaining($"Pushed image '{imageArm64}' to registry") .And.HaveStdOutContaining($"Pushed image index '{imageIndex}' to registry '{registry}'"); @@ -945,11 +1080,11 @@ public void EndToEndMultiArch_RemoteRegistry() newProjectDir.Delete(true); } - [DockerAvailableFact] + [DockerAvailableFact(Skip = "https://github.com/dotnet/sdk/issues/45181")] public void EndToEndMultiArch_ContainerRuntimeIdentifiersOverridesRuntimeIdentifiers() { // Create a new console project - DirectoryInfo newProjectDir = CreateNewProject("console"); + DirectoryInfo newProjectDir = CreateNewProject("console", _oldFramework); string imageName = NewImageName(); string imageTag = "1.0"; @@ -971,8 +1106,8 @@ public void EndToEndMultiArch_ContainerRuntimeIdentifiersOverridesRuntimeIdentif // Check that the app was published only for RID from ContainerRuntimeIdentifiers // images were created locally only for RID for from ContainerRuntimeIdentifiers commandResult.Should().Pass() - .And.NotHaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, "linux-x64")) - .And.HaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, "linux-arm64")) + .And.NotHaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, _oldFramework, "linux-x64")) + .And.HaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, _oldFramework, "linux-arm64")) .And.NotHaveStdOutContaining($"Pushed image '{imageName}:{imageTag}-linux-x64' to local registry") .And.HaveStdOutContaining($"Pushed image '{imageName}:{imageTag}-linux-arm64' to local registry"); @@ -989,7 +1124,7 @@ public void EndToEndMultiArch_EnvVariables() string imageArm64 = $"{imageName}:{imageTag}-linux-arm64"; // Create new console app, set ContainerEnvironmentVariables, and set to output env variable - DirectoryInfo newProjectDir = CreateNewProject("console"); + DirectoryInfo newProjectDir = CreateNewProject("console", _oldFramework); var csprojPath = Path.Combine(newProjectDir.FullName, $"{nameof(EndToEndMultiArch_EnvVariables)}.csproj"); var csprojContent = File.ReadAllText(csprojPath); csprojContent = csprojContent.Replace("", @@ -1056,7 +1191,7 @@ public void EndToEndMultiArch_Ports() string imageArm64 = $"{imageName}:{imageTag}-linux-arm64"; // Create new web app, set ContainerPort - DirectoryInfo newProjectDir = CreateNewProject("webapp"); + DirectoryInfo newProjectDir = CreateNewProject("webapp", _oldFramework); var csprojPath = Path.Combine(newProjectDir.FullName, $"{nameof(EndToEndMultiArch_Ports)}.csproj"); var csprojContent = File.ReadAllText(csprojPath); csprojContent = csprojContent.Replace("", @@ -1155,7 +1290,7 @@ public void EndToEndMultiArch_Labels() // Run PublishContainer for multi-arch with ContainerGenerateLabels new DotnetCommand( _testOutput, - "build", + "publish", "/t:PublishContainer", "/p:RuntimeIdentifiers=\"linux-x64;linux-arm64\"", $"/p:ContainerBaseImage={DockerRegistryManager.FullyQualifiedBaseImageAspNet}", diff --git a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopLibrary.cs b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopLibrary.cs index fe41cd5525de..7b47bc1b87d4 100644 --- a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopLibrary.cs +++ b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopLibrary.cs @@ -227,32 +227,6 @@ public void It_can_preserve_compilation_context_and_reference_netstandard_librar } } - [Theory] - [InlineData("RazorSimpleMvc22", "netcoreapp2.2", "SimpleMvc22")] - [InlineData("DesktopReferencingNetStandardLibrary", "net46", "Library")] - public void PackageReferences_with_private_assets_do_not_appear_in_deps_file(string asset, string targetFramework, string exeName) - { - var testAsset = _testAssetsManager - .CopyTestAsset(asset) - .WithSource(); - - var buildCommand = new BuildCommand(testAsset); - buildCommand.Execute().Should().Pass(); - - using (var depsJsonFileStream = File.OpenRead(Path.Combine(buildCommand.GetOutputDirectory(targetFramework).FullName, exeName + ".deps.json"))) - { - var dependencyContext = new DependencyContextJsonReader().Read(depsJsonFileStream); - if (asset.Equals("DesktopReferencingNetStandardLibrary")) - { - dependencyContext.CompileLibraries.Any(l => l.Name.Equals("Library")).Should().BeTrue(); - } - else - { - dependencyContext.CompileLibraries.Any(l => l.Name.Equals("Microsoft.AspNetCore.App")).Should().BeFalse(); - } - } - } - [WindowsOnlyFact] public void It_resolves_assembly_conflicts_with_a_NETFramework_library() { diff --git a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildANetCoreApp.cs b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildANetCoreApp.cs index 9d0699ce8040..89e5c20a26b0 100644 --- a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildANetCoreApp.cs +++ b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildANetCoreApp.cs @@ -4,6 +4,7 @@ #nullable disable using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using Microsoft.Extensions.DependencyModel; using Microsoft.NET.Build.Tasks; using Newtonsoft.Json.Linq; @@ -50,7 +51,7 @@ public void It_targets_the_right_shared_framework(string targetFramework, string } // Test behavior when implicit version differs for framework-dependent and self-contained apps - [Theory(Skip = "https://github.com/dotnet/sdk/issues/45417")] + [Theory] [InlineData("netcoreapp1.0", false, true, "1.0.5")] [InlineData("netcoreapp1.0", true, true, "1.0.16")] [InlineData("netcoreapp1.0", false, false, "1.0.5")] @@ -167,7 +168,8 @@ private void It_targets_the_right_framework( var additionalProbingPaths = ((JArray)devruntimeConfig["runtimeOptions"]["additionalProbingPaths"]).Values(); // can't use Path.Combine on segments with an illegal `|` character - var expectedPath = $"{Path.Combine(FileConstants.UserProfileFolder, ".dotnet", "store")}{Path.DirectorySeparatorChar}|arch|{Path.DirectorySeparatorChar}|tfm|"; + var homePath = Environment.GetEnvironmentVariable(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "USERPROFILE" : "HOME"); + var expectedPath = $"{Path.Combine(homePath, ".dotnet", "store")}{Path.DirectorySeparatorChar}|arch|{Path.DirectorySeparatorChar}|tfm|"; additionalProbingPaths.Should().Contain(expectedPath); } @@ -269,7 +271,7 @@ public void It_runs_the_app_from_the_output_folder(string targetFramework) [InlineData("net7.0")] [InlineData(ToolsetInfo.CurrentTargetFramework)] public void It_runs_a_rid_specific_app_from_the_output_folder(string targetFramework) - { + { RunAppFromOutputFolder("RunFromOutputFolderWithRID_" + targetFramework, true, false, targetFramework); } @@ -1001,7 +1003,7 @@ public void It_warns_on_nonportable_rids(string targetFramework, string[] rids, IsExe = true }; - // Reference the package, add it to restore sources, and use a test-specific packages folder + // Reference the package, add it to restore sources, and use a test-specific packages folder testProject.PackageReferences.Add(package); testProject.AdditionalProperties["RestoreAdditionalProjectSources"] = Path.GetDirectoryName(package.NupkgPath); testProject.AdditionalProperties["RestorePackagesPath"] = @"$(MSBuildProjectDirectory)\packages"; @@ -1054,7 +1056,7 @@ public void It_does_not_warn_on_rids_if_no_framework_references() IsExe = true }; - // Reference the package, add it to restore sources, and use a test-specific packages folder + // Reference the package, add it to restore sources, and use a test-specific packages folder testProject.PackageReferences.Add(package); testProject.AdditionalProperties["RestoreAdditionalProjectSources"] = Path.GetDirectoryName(package.NupkgPath); testProject.AdditionalProperties["RestorePackagesPath"] = @"$(MSBuildProjectDirectory)\packages"; diff --git a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildAWindowsDesktopProject.cs b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildAWindowsDesktopProject.cs index 84b92ebee3d8..9f2d59cbab70 100644 --- a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildAWindowsDesktopProject.cs +++ b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildAWindowsDesktopProject.cs @@ -455,8 +455,9 @@ public void ItUsesTheHighestMatchingWindowsSdkPackageVersion(string targetFramew } + // We used to emit NETSDK1219 while UWP support on .NET 9 was not GA yet, make sure it's gone now [WindowsOnlyFact] - public void ItWarnsWhenBuildingAProjectWithUseUwpProperty() + public void ItDoesNotWarnAnymoreWhenBuildingAProjectWithUseUwpProperty() { TestProject testProject = new() { @@ -474,7 +475,7 @@ public void ItWarnsWhenBuildingAProjectWithUseUwpProperty() .Should() .Pass() .And - .HaveStdOutContaining("NETSDK1219"); + .NotHaveStdOutContaining("NETSDK1219"); } [WindowsOnlyFact] diff --git a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToResolveConflicts.cs b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToResolveConflicts.cs index 20d3bd72dcb8..e1bc0efcb098 100644 --- a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToResolveConflicts.cs +++ b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToResolveConflicts.cs @@ -3,7 +3,11 @@ #nullable disable +using System.Text.Json.Nodes; using System.Text.RegularExpressions; +using NuGet.Common; +using NuGet.Frameworks; +using NuGet.ProjectModel; namespace Microsoft.NET.Build.Tests { @@ -260,5 +264,96 @@ public void AnalyzersAreConflictResolved() .Should() .Pass(); } + + // Should also run on full framework, but needs the right version of NuGet, which isn't on CI yet + [CoreMSBuildOnlyTheory] + [InlineData(true)] + [InlineData(false)] + public void PlatformPackagesCanBePruned(bool prunePackages) + { + var referencedProject = new TestProject("ReferencedProject") + { + TargetFrameworks = ToolsetInfo.CurrentTargetFramework, + IsExe = false + }; + referencedProject.PackageReferences.Add(new TestPackageReference("System.Text.Json", "8.0.0")); + + var testProject = new TestProject() + { + TargetFrameworks = ToolsetInfo.CurrentTargetFramework + }; + + testProject.AdditionalProperties["RestoreEnablePackagePruning"] = prunePackages.ToString(); + testProject.ReferencedProjects.Add(referencedProject); + + var testAsset = _testAssetsManager.CreateTestProject(testProject, identifier: prunePackages.ToString()); + + var buildCommand = new BuildCommand(testAsset); + + buildCommand.Execute().Should().Pass(); + + var assetsFilePath = Path.Combine(buildCommand.GetBaseIntermediateDirectory().FullName, "project.assets.json"); + var lockFile = LockFileUtilities.GetLockFile(assetsFilePath, new NullLogger()); + var lockFileTarget = lockFile.GetTarget(NuGetFramework.Parse(ToolsetInfo.CurrentTargetFramework), runtimeIdentifier: null); + + if (prunePackages) + { + lockFileTarget.Libraries.Should().NotContain(library => library.Name.Equals("System.Text.Json", StringComparison.OrdinalIgnoreCase)); + } + else + { + lockFileTarget.Libraries.Should().Contain(library => library.Name.Equals("System.Text.Json", StringComparison.OrdinalIgnoreCase)); + } + } + + [Fact] + public void TransitiveFrameworkReferencesDoNotAffectPruning() + { + var referencedProject = new TestProject("ReferencedProject") + { + TargetFrameworks = ToolsetInfo.CurrentTargetFramework, + IsExe = false + }; + referencedProject.PackageReferences.Add(new TestPackageReference("System.Text.Json", "8.0.0")); + referencedProject.FrameworkReferences.Add("Microsoft.AspNetCore.App"); + + var testProject = new TestProject() + { + TargetFrameworks = ToolsetInfo.CurrentTargetFramework + }; + + testProject.AdditionalProperties["RestoreEnablePackagePruning"] = "True"; + testProject.ReferencedProjects.Add(referencedProject); + + var testAsset = _testAssetsManager.CreateTestProject(testProject); + + new BuildCommand(testAsset).Execute().Should().Pass(); + + var getItemsCommand1 = new MSBuildCommand(testAsset, "AddPrunePackageReferences"); + var itemsResult1 = getItemsCommand1.Execute("-getItem:PrunePackageReference"); + itemsResult1.Should().Pass(); + + var items1 = ParseItemsJson(itemsResult1.StdOut); + + var getItemsCommand2 = new MSBuildCommand(testAsset, "ResolvePackageAssets;AddTransitiveFrameworkReferences;AddPrunePackageReferences"); + var itemsResult2 = getItemsCommand2.Execute("-getItem:PrunePackageReference"); + itemsResult2.Should().Pass(); + + var items2 = ParseItemsJson(itemsResult2.StdOut); + + items2.Should().BeEquivalentTo(items1); + + static List> ParseItemsJson(string json) + { + List> ret = new(); + var root = JsonNode.Parse(json); + var items = (JsonArray) root["Items"]["PrunePackageReference"]; + foreach (var item in items) + { + ret.Add(new KeyValuePair((string)item["Identity"], (string)item["Version"])); + } + return ret; + } + } } } diff --git a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToUseAnalyzers.cs b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToUseAnalyzers.cs index 4f95bee44cb0..4eee335ee8e2 100644 --- a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToUseAnalyzers.cs +++ b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToUseAnalyzers.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. #nullable disable +using Microsoft.DotNet.Configurer; namespace Microsoft.NET.Build.Tests { @@ -258,7 +259,7 @@ public void It_resolves_multitargeted_analyzers() static readonly List nugetRoots = new() { TestContext.Current.NuGetCachePath, - Path.Combine(FileConstants.UserProfileFolder, ".dotnet", "NuGetFallbackFolder"), + Path.Combine(CliFolderPathCalculator.DotnetHomePath, ".dotnet", "NuGetFallbackFolder"), Path.Combine(TestContext.Current.ToolsetUnderTest.DotNetRoot, "packs") }; diff --git a/test/Microsoft.NET.Build.Tests/Microsoft.NET.Build.Tests.csproj b/test/Microsoft.NET.Build.Tests/Microsoft.NET.Build.Tests.csproj index 4093bb3cae8b..dcc4e655313c 100644 --- a/test/Microsoft.NET.Build.Tests/Microsoft.NET.Build.Tests.csproj +++ b/test/Microsoft.NET.Build.Tests/Microsoft.NET.Build.Tests.csproj @@ -34,9 +34,10 @@ - + + @@ -53,5 +54,5 @@ - + diff --git a/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAProjectWithAllFeatures.cs b/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAProjectWithAllFeatures.cs index 50c8c9750ba0..8219179ff114 100644 --- a/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAProjectWithAllFeatures.cs +++ b/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAProjectWithAllFeatures.cs @@ -71,10 +71,12 @@ public void It_publishes_the_project_correctly(string targetFramework, string[] ""System.Diagnostics.Tracing.EventSource.IsSupported"": false, ""System.Drawing.Design.UITypeEditor.IsSupported"": true, ""System.Globalization.Invariant"": true, + ""System.TimeZoneInfo.Invariant"": true, ""System.Globalization.PredefinedCulturesOnly"": true, ""System.GC.Concurrent"": false, ""System.GC.Server"": true, ""System.GC.RetainVM"": false, + ""System.Linq.Enumerable.IsSizeOptimized"": true, ""System.Net.Http.EnableActivityPropagation"": false, ""System.Net.Http.UseNativeHttpHandler"": true, ""System.Net.Security.UseManagedNtlm"": true, diff --git a/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAnAotApp.cs b/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAnAotApp.cs index d2bcb4393300..04d8c8c0bdb0 100644 --- a/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAnAotApp.cs +++ b/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAnAotApp.cs @@ -21,7 +21,7 @@ public GivenThatWeWantToPublishAnAotApp(ITestOutputHelper log) : base(log) { } - [RequiresMSBuildVersionTheory("17.12.0")] + [RequiresMSBuildVersionTheory("17.12.0", Skip = "https://github.com/dotnet/sdk/issues/46006")] [MemberData(nameof(Net7Plus), MemberType = typeof(PublishTestUtils))] public void NativeAot_hw_runs_with_no_warnings_when_PublishAot_is_enabled(string targetFramework) { diff --git a/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/Build_DoesNotGenerateManifestJson_IncludesJSModulesOnBlazorBootJsonManifest.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/Build_DoesNotGenerateManifestJson_IncludesJSModulesOnBlazorBootJsonManifest.Build.staticwebassets.json index 13026143feea..954e65cb28a9 100644 --- a/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/Build_DoesNotGenerateManifestJson_IncludesJSModulesOnBlazorBootJsonManifest.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/Build_DoesNotGenerateManifestJson_IncludesJSModulesOnBlazorBootJsonManifest.Build.staticwebassets.json @@ -1696,6 +1696,27 @@ "CopyToPublishDirectory": "Never", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\webcil\\System.IO.wasm" }, + { + "Identity": "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm", + "SourceId": "blazorwasm-minimal", + "SourceType": "Computed", + "ContentRoot": "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\", + "BasePath": "/", + "RelativePath": "_framework/System.Linq.AsyncEnumerable.wasm", + "AssetKind": "Build", + "AssetMode": "All", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "WasmResource", + "AssetTraitValue": "runtime", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "PreserveNewest", + "CopyToPublishDirectory": "Never", + "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\webcil\\System.Linq.AsyncEnumerable.wasm" + }, { "Identity": "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.Expressions.wasm", "SourceId": "blazorwasm-minimal", @@ -5980,6 +6001,27 @@ "CopyToPublishDirectory": "Never", "OriginalItemSpec": "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\_framework\\System.IO.wasm.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.AsyncEnumerable.wasm.gz", + "SourceId": "blazorwasm-minimal", + "SourceType": "Computed", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "/", + "RelativePath": "_framework/System.Linq.AsyncEnumerable.wasm.gz", + "AssetKind": "Build", + "AssetMode": "All", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "PreserveNewest", + "CopyToPublishDirectory": "Never", + "OriginalItemSpec": "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\_framework\\System.Linq.AsyncEnumerable.wasm.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.Expressions.wasm.gz", "SourceId": "blazorwasm-minimal", @@ -11672,6 +11714,43 @@ } ] }, + { + "Route": "_framework/System.Linq.AsyncEnumerable.wasm", + "AssetFile": "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "application/wasm" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, { "Route": "_framework/System.Linq.Expressions.wasm", "AssetFile": "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.Expressions.wasm", @@ -24260,6 +24339,106 @@ } ] }, + { + "Route": "_framework/System.Linq.AsyncEnumerable.wasm.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.AsyncEnumerable.wasm.gz", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "application/wasm" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/System.Linq.AsyncEnumerable.wasm", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.AsyncEnumerable.wasm.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "application/wasm" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, { "Route": "_framework/System.Linq.Expressions.wasm.gz", "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.Expressions.wasm.gz", diff --git a/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/JSModules_ManifestIncludesModuleTargetPaths.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/JSModules_ManifestIncludesModuleTargetPaths.Build.staticwebassets.json index b232989a9a81..39ad6044966c 100644 --- a/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/JSModules_ManifestIncludesModuleTargetPaths.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/JSModules_ManifestIncludesModuleTargetPaths.Build.staticwebassets.json @@ -1810,6 +1810,27 @@ "CopyToPublishDirectory": "Never", "OriginalItemSpec": "${ProjectPath}\\blazorwasm\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.IO.wasm" }, + { + "Identity": "${ProjectPath}\\blazorwasm\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm", + "SourceId": "blazorwasm", + "SourceType": "Project", + "ContentRoot": "${ProjectPath}\\blazorwasm\\bin\\Debug\\${Tfm}\\wwwroot\\", + "BasePath": "/", + "RelativePath": "_framework/System.Linq.AsyncEnumerable.wasm", + "AssetKind": "Build", + "AssetMode": "All", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "WasmResource", + "AssetTraitValue": "runtime", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "PreserveNewest", + "CopyToPublishDirectory": "Never", + "OriginalItemSpec": "${ProjectPath}\\blazorwasm\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm" + }, { "Identity": "${ProjectPath}\\blazorwasm\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.Expressions.wasm", "SourceId": "blazorwasm", @@ -6157,6 +6178,27 @@ "CopyToPublishDirectory": "Never", "OriginalItemSpec": "${ProjectPath}\\blazorwasm\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.IO.wasm.gz" }, + { + "Identity": "${ProjectPath}\\blazorwasm\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.AsyncEnumerable.wasm.gz", + "SourceId": "blazorwasm", + "SourceType": "Project", + "ContentRoot": "${ProjectPath}\\blazorwasm\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "/", + "RelativePath": "_framework/System.Linq.AsyncEnumerable.wasm.gz", + "AssetKind": "Build", + "AssetMode": "All", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${ProjectPath}\\blazorwasm\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "PreserveNewest", + "CopyToPublishDirectory": "Never", + "OriginalItemSpec": "${ProjectPath}\\blazorwasm\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.AsyncEnumerable.wasm.gz" + }, { "Identity": "${ProjectPath}\\blazorwasm\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.Expressions.wasm.gz", "SourceId": "blazorwasm", @@ -12291,6 +12333,43 @@ } ] }, + { + "Route": "_framework/System.Linq.AsyncEnumerable.wasm", + "AssetFile": "${ProjectPath}\\blazorwasm\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "application/wasm" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, { "Route": "_framework/System.Linq.Expressions.wasm", "AssetFile": "${ProjectPath}\\blazorwasm\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.Expressions.wasm", @@ -25179,6 +25258,106 @@ } ] }, + { + "Route": "_framework/System.Linq.AsyncEnumerable.wasm.gz", + "AssetFile": "${ProjectPath}\\blazorwasm\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.AsyncEnumerable.wasm.gz", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "application/wasm" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/System.Linq.AsyncEnumerable.wasm", + "AssetFile": "${ProjectPath}\\blazorwasm\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.AsyncEnumerable.wasm.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "application/wasm" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, { "Route": "_framework/System.Linq.Expressions.wasm.gz", "AssetFile": "${ProjectPath}\\blazorwasm\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.Expressions.wasm.gz", diff --git a/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/StaticWebAssets_BuildMinimal_Works.Build.files.json b/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/StaticWebAssets_BuildMinimal_Works.Build.files.json index c041d33230f0..159437eca94a 100644 --- a/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/StaticWebAssets_BuildMinimal_Works.Build.files.json +++ b/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/StaticWebAssets_BuildMinimal_Works.Build.files.json @@ -79,6 +79,7 @@ "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.IO.Pipes.wasm", "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.IO.UnmanagedMemoryStream.wasm", "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.IO.wasm", + "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm", "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.Expressions.wasm", "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.Parallel.wasm", "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.Queryable.wasm", @@ -283,6 +284,7 @@ "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.IO.Pipes.wasm.gz", "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.IO.UnmanagedMemoryStream.wasm.gz", "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.IO.wasm.gz", + "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.AsyncEnumerable.wasm.gz", "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.Expressions.wasm.gz", "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.Parallel.wasm.gz", "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.Queryable.wasm.gz", @@ -571,6 +573,8 @@ "${OutputPath}\\wwwroot\\_framework\\System.IO.UnmanagedMemoryStream.wasm.gz", "${OutputPath}\\wwwroot\\_framework\\System.IO.wasm", "${OutputPath}\\wwwroot\\_framework\\System.IO.wasm.gz", + "${OutputPath}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm", + "${OutputPath}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm.gz", "${OutputPath}\\wwwroot\\_framework\\System.Linq.Expressions.wasm", "${OutputPath}\\wwwroot\\_framework\\System.Linq.Expressions.wasm.gz", "${OutputPath}\\wwwroot\\_framework\\System.Linq.Parallel.wasm", diff --git a/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/StaticWebAssets_BuildMinimal_Works.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/StaticWebAssets_BuildMinimal_Works.Build.staticwebassets.json index 7d3ea2824a48..21c807aba71e 100644 --- a/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/StaticWebAssets_BuildMinimal_Works.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/StaticWebAssets_BuildMinimal_Works.Build.staticwebassets.json @@ -1696,6 +1696,27 @@ "CopyToPublishDirectory": "Never", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\webcil\\System.IO.wasm" }, + { + "Identity": "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm", + "SourceId": "blazorwasm-minimal", + "SourceType": "Computed", + "ContentRoot": "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\", + "BasePath": "/", + "RelativePath": "_framework/System.Linq.AsyncEnumerable.wasm", + "AssetKind": "Build", + "AssetMode": "All", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "WasmResource", + "AssetTraitValue": "runtime", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "PreserveNewest", + "CopyToPublishDirectory": "Never", + "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\webcil\\System.Linq.AsyncEnumerable.wasm" + }, { "Identity": "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.Expressions.wasm", "SourceId": "blazorwasm-minimal", @@ -5980,6 +6001,27 @@ "CopyToPublishDirectory": "Never", "OriginalItemSpec": "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\_framework\\System.IO.wasm.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.AsyncEnumerable.wasm.gz", + "SourceId": "blazorwasm-minimal", + "SourceType": "Computed", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "/", + "RelativePath": "_framework/System.Linq.AsyncEnumerable.wasm.gz", + "AssetKind": "Build", + "AssetMode": "All", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "PreserveNewest", + "CopyToPublishDirectory": "Never", + "OriginalItemSpec": "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\_framework\\System.Linq.AsyncEnumerable.wasm.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.Expressions.wasm.gz", "SourceId": "blazorwasm-minimal", @@ -11756,6 +11798,43 @@ } ] }, + { + "Route": "_framework/System.Linq.AsyncEnumerable.wasm", + "AssetFile": "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "application/wasm" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, { "Route": "_framework/System.Linq.Expressions.wasm", "AssetFile": "${ProjectPath}\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.Expressions.wasm", @@ -24344,6 +24423,106 @@ } ] }, + { + "Route": "_framework/System.Linq.AsyncEnumerable.wasm.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.AsyncEnumerable.wasm.gz", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "application/wasm" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/System.Linq.AsyncEnumerable.wasm", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.AsyncEnumerable.wasm.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "application/wasm" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, { "Route": "_framework/System.Linq.Expressions.wasm.gz", "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.Expressions.wasm.gz", diff --git a/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/StaticWebAssets_Build_Hosted_Works.Build.files.json b/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/StaticWebAssets_Build_Hosted_Works.Build.files.json index ff83f774df44..39cefdad83e5 100644 --- a/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/StaticWebAssets_Build_Hosted_Works.Build.files.json +++ b/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/StaticWebAssets_Build_Hosted_Works.Build.files.json @@ -163,6 +163,8 @@ "${OutputPath}\\wwwroot\\_framework\\System.IO.UnmanagedMemoryStream.wasm.gz", "${OutputPath}\\wwwroot\\_framework\\System.IO.wasm", "${OutputPath}\\wwwroot\\_framework\\System.IO.wasm.gz", + "${OutputPath}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm", + "${OutputPath}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm.gz", "${OutputPath}\\wwwroot\\_framework\\System.Linq.Expressions.wasm", "${OutputPath}\\wwwroot\\_framework\\System.Linq.Expressions.wasm.gz", "${OutputPath}\\wwwroot\\_framework\\System.Linq.Parallel.wasm", diff --git a/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/StaticWebAssets_Build_Hosted_Works.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/StaticWebAssets_Build_Hosted_Works.Build.staticwebassets.json index 2a7f4c1d7f83..bc54d764bbfd 100644 --- a/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/StaticWebAssets_Build_Hosted_Works.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/StaticWebAssetsBaselines/StaticWebAssets_Build_Hosted_Works.Build.staticwebassets.json @@ -1768,6 +1768,27 @@ "CopyToPublishDirectory": "Never", "OriginalItemSpec": "${ProjectPath}\\blazorwasm\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.IO.wasm" }, + { + "Identity": "${ProjectPath}\\blazorwasm\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm", + "SourceId": "blazorwasm", + "SourceType": "Project", + "ContentRoot": "${ProjectPath}\\blazorwasm\\bin\\Debug\\${Tfm}\\wwwroot\\", + "BasePath": "/", + "RelativePath": "_framework/System.Linq.AsyncEnumerable.wasm", + "AssetKind": "Build", + "AssetMode": "All", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "WasmResource", + "AssetTraitValue": "runtime", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "PreserveNewest", + "CopyToPublishDirectory": "Never", + "OriginalItemSpec": "${ProjectPath}\\blazorwasm\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm" + }, { "Identity": "${ProjectPath}\\blazorwasm\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.Expressions.wasm", "SourceId": "blazorwasm", @@ -6115,6 +6136,27 @@ "CopyToPublishDirectory": "Never", "OriginalItemSpec": "${ProjectPath}\\blazorwasm\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.IO.wasm.gz" }, + { + "Identity": "${ProjectPath}\\blazorwasm\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.AsyncEnumerable.wasm.gz", + "SourceId": "blazorwasm", + "SourceType": "Project", + "ContentRoot": "${ProjectPath}\\blazorwasm\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "/", + "RelativePath": "_framework/System.Linq.AsyncEnumerable.wasm.gz", + "AssetKind": "Build", + "AssetMode": "All", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${ProjectPath}\\blazorwasm\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "PreserveNewest", + "CopyToPublishDirectory": "Never", + "OriginalItemSpec": "${ProjectPath}\\blazorwasm\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.AsyncEnumerable.wasm.gz" + }, { "Identity": "${ProjectPath}\\blazorwasm\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.Expressions.wasm.gz", "SourceId": "blazorwasm", @@ -12028,6 +12070,43 @@ } ] }, + { + "Route": "_framework/System.Linq.AsyncEnumerable.wasm", + "AssetFile": "${ProjectPath}\\blazorwasm\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.AsyncEnumerable.wasm", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "application/wasm" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, { "Route": "_framework/System.Linq.Expressions.wasm", "AssetFile": "${ProjectPath}\\blazorwasm\\bin\\Debug\\${Tfm}\\wwwroot\\_framework\\System.Linq.Expressions.wasm", @@ -24916,6 +24995,106 @@ } ] }, + { + "Route": "_framework/System.Linq.AsyncEnumerable.wasm.gz", + "AssetFile": "${ProjectPath}\\blazorwasm\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.AsyncEnumerable.wasm.gz", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "application/wasm" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/System.Linq.AsyncEnumerable.wasm", + "AssetFile": "${ProjectPath}\\blazorwasm\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.AsyncEnumerable.wasm.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "application/wasm" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, { "Route": "_framework/System.Linq.Expressions.wasm.gz", "AssetFile": "${ProjectPath}\\blazorwasm\\obj\\Debug\\${Tfm}\\compressed\\_framework\\System.Linq.Expressions.wasm.gz", diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/MvcBuildIntegrationTestLegacy.cs b/test/Microsoft.NET.Sdk.Razor.Tests/MvcBuildIntegrationTestLegacy.cs index 2453cbeaf638..f223c1a15208 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/MvcBuildIntegrationTestLegacy.cs +++ b/test/Microsoft.NET.Sdk.Razor.Tests/MvcBuildIntegrationTestLegacy.cs @@ -115,18 +115,9 @@ public void Build_ProducesDepsFileWithCompilationContext_ButNoReferences() depsFile.Should().Exist(); var dependencyContext = ReadDependencyContext(depsFile.FullName); - if (TargetFramework.Equals("netcoreapp2.2")) - { - // Ensure compile references from a PrivateAssets="all" PackageReference don't exist - var packageReference = dependencyContext.CompileLibraries.FirstOrDefault(l => l.Name == "System.Runtime.CompilerServices.Unsafe", defaultValue: null); - packageReference.Should().BeNull(); - } - else - { - // Ensure some compile references exist - var packageReference = dependencyContext.CompileLibraries.First(l => l.Name == "System.Runtime.CompilerServices.Unsafe"); - packageReference.Assemblies.Should().NotBeEmpty(); - } + // Ensure some compile references exist + var packageReference = dependencyContext.CompileLibraries.First(l => l.Name == "System.Runtime.CompilerServices.Unsafe"); + packageReference.Assemblies.Should().NotBeEmpty(); var projectReference = dependencyContext.CompileLibraries.First(l => l.Name == TestProjectName); projectReference.Assemblies.Should().NotBeEmpty(); diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetEndpointsIntegrationTest.cs b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetEndpointsIntegrationTest.cs index e6f5aa5a6a00..8f844304d234 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetEndpointsIntegrationTest.cs +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetEndpointsIntegrationTest.cs @@ -41,7 +41,11 @@ public void Build_CreatesEndpointsForAssets() var manifest = StaticWebAssetsManifest.FromJsonBytes(File.ReadAllBytes(path)); var endpoints = manifest.Endpoints; - endpoints.Should().HaveCount(15); + // blazor.server.js and blazor.web.js assets and endpoints are included automatically + // based on the presence of .razor files in projects referencing the web SDK. + // In the future we will filter these out based on whether the app references the Endpoints or the Server + // assemblies, but for now, just account for them in the tests and ignore them. + endpoints.Should().HaveCount(27); var appJsEndpoints = endpoints.Where(ep => ep.Route.EndsWith("app.js")); appJsEndpoints.Should().HaveCount(2); var appJsGzEndpoints = endpoints.Where(ep => ep.Route.EndsWith("app.js.gz")); @@ -197,7 +201,11 @@ public void Publish_CreatesEndpointsForAssets() file.Length.Should().Be(length, $"because {endpoint.Route} {file.FullName}"); } - endpoints.Should().HaveCount(25); + // blazor.server.js and blazor.web.js assets and endpoints are included automatically + // based on the presence of .razor files in projects referencing the web SDK. + // In the future we will filter these out based on whether the app references the Endpoints or the Server + // assemblies, but for now, just account for them in the tests and ignore them. + endpoints.Should().HaveCount(45); var appJsEndpoints = endpoints.Where(ep => ep.Route.EndsWith("app.js")); appJsEndpoints.Should().HaveCount(3); var appJsGzEndpoints = endpoints.Where(ep => ep.Route.EndsWith("app.js.gz")); @@ -392,7 +400,11 @@ public void Publish_CreatesEndpointsForAssets_BuildAndPublish_Assets() var fingerprintedAppBundleEndpoints = endpoints.Where(MatchUncompressedAppBundleWithFingerprint); fingerprintedAppBundleEndpoints.Should().HaveCount(3); - endpoints.Should().HaveCount(25); + // blazor.server.js and blazor.web.js assets and endpoints are included automatically + // based on the presence of .razor files in projects referencing the web SDK. + // In the future we will filter these out based on whether the app references the Endpoints or the Server + // assemblies, but for now, just account for them in the tests and ignore them. + endpoints.Should().HaveCount(45); AssertManifest(publishManifest, LoadPublishManifest()); } diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselineFactory.cs b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselineFactory.cs index 9cd572ca1740..73ebfe5fcaea 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselineFactory.cs +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselineFactory.cs @@ -56,6 +56,8 @@ public partial class StaticWebAssetsBaselineFactory public IList KnownFilePrefixesWithHashOrVersion { get; } = [ + "blazor.web.", + "blazor.server", "dotnet.runtime", "dotnet.native", "dotnet" @@ -425,6 +427,10 @@ private static string ReplaceSegments(string file, Func s private string RemovePossibleHash(string fileNameAndExtension) { var filename = KnownFilePrefixesWithHashOrVersion.FirstOrDefault(p => fileNameAndExtension.StartsWith(p)); + if (filename != null && filename.EndsWith(".")) + { + filename = filename[..^1]; + } var extension = KnownExtensions.FirstOrDefault(f => fileNameAndExtension.EndsWith(f, StringComparison.OrdinalIgnoreCase)); if (filename != null && extension != null) { diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_CreatesEndpointsForAssets.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_CreatesEndpointsForAssets.Build.staticwebassets.json index 4704aa3a0a40..ed9b1f3074d8 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_CreatesEndpointsForAssets.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_CreatesEndpointsForAssets.Build.staticwebassets.json @@ -58,6 +58,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\app.js.gz", "SourceId": "ComponentApp", @@ -141,6 +183,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "wwwroot\\app.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -577,8 +661,8 @@ ] }, { - "Route": "app.js.gz", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\app.js.gz", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -622,15 +706,9 @@ ] }, { - "Route": "app.js", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\app.js.gz", - "Selectors": [ - { - "Name": "Content-Encoding", - "Value": "gzip", - "Quality": "__quality__" - } - ], + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -638,7 +716,7 @@ }, { "Name": "Cache-Control", - "Value": "no-cache" + "Value": "max-age=31536000, immutable" }, { "Name": "Content-Encoding", @@ -656,10 +734,6 @@ "Name": "ETag", "Value": "__etag__" }, - { - "Name": "ETag", - "Value": "__etag__" - }, { "Name": "Last-Modified", "Value": "__last-modified__" @@ -670,16 +744,30 @@ } ], "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, { "Name": "integrity", "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", - "Selectors": [], + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -689,13 +777,21 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "ETag", @@ -704,6 +800,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -714,9 +814,15 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", - "Selectors": [], + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -726,13 +832,21 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "ETag", @@ -741,6 +855,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -754,13 +872,13 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.server.js" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -771,13 +889,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -786,6 +908,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -796,8 +922,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -808,13 +934,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -823,6 +953,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -836,14 +970,20 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.web.js.gz" } ] }, { - "Route": "app.js", - "AssetFile": "${ProjectPath}\\wwwroot\\app.js", - "Selectors": [], + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -853,6 +993,65 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -865,15 +1064,496 @@ "Name": "ETag", "Value": "__etag__" }, + { + "Name": "ETag", + "Value": "__etag__" + }, { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, { "Name": "integrity", "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] + }, + { + "Route": "app.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\app.js.gz", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "app.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\app.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "app.js", + "AssetFile": "${ProjectPath}\\wwwroot\\app.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" } ] } diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DeployOnBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DeployOnBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Build.staticwebassets.json index 6d6cea45277d..10ce4469cc28 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DeployOnBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DeployOnBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Build.staticwebassets.json @@ -50,6 +50,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", "SourceId": "ComponentApp", @@ -91,6 +133,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -527,8 +611,8 @@ ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -539,13 +623,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -554,6 +642,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -564,8 +656,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -576,13 +668,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -591,6 +687,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -604,13 +704,131 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -621,13 +839,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -636,6 +858,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -646,8 +872,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -658,13 +884,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -673,6 +903,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -686,7 +920,453 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.web.js.gz" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" } ] } diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DeployOnBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.files.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DeployOnBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.files.json index 8fe45cab05c6..491743598308 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DeployOnBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.files.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DeployOnBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.files.json @@ -2,6 +2,12 @@ "${OutputPath}\\wwwroot\\ComponentApp.styles.css", "${OutputPath}\\wwwroot\\ComponentApp.styles.css.br", "${OutputPath}\\wwwroot\\ComponentApp.styles.css.gz", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js.br", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js.gz", + "${OutputPath}\\wwwroot\\_framework\\blazor.web.js", + "${OutputPath}\\wwwroot\\_framework\\blazor.web.js.br", + "${OutputPath}\\wwwroot\\_framework\\blazor.web.js.gz", "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.gz", "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz", "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", @@ -10,5 +16,11 @@ "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", "${OutputPath}\\wwwroot\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", "${OutputPath}\\wwwroot\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz", - "${OutputPath}\\wwwroot\\ComponentApp#[.{fingerprint}]?.styles.css" + "${OutputPath}\\wwwroot\\ComponentApp#[.{fingerprint}]?.styles.css", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js.br", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js.gz", + "${OutputPath}\\wwwroot\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "${OutputPath}\\wwwroot\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "${OutputPath}\\wwwroot\\_framework\\blazor.web#[.{fingerprint}]?.js" ] \ No newline at end of file diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DeployOnBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DeployOnBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.staticwebassets.json index 109d70f6bf4b..b3b9db6e7320 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DeployOnBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DeployOnBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.staticwebassets.json @@ -50,6 +50,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", "SourceId": "ComponentApp", @@ -92,6 +134,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.br", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "br", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.br" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "br", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", "SourceId": "ComponentApp", @@ -133,6 +217,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -569,8 +695,8 @@ ] }, { - "Route": "ComponentApp.bundle.scp.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -583,7 +709,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -591,7 +717,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -614,8 +740,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -628,7 +754,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -636,7 +762,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -662,17 +788,17 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css.br" + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -687,7 +813,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -695,7 +821,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -722,12 +848,12 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -742,7 +868,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -750,7 +876,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -780,13 +906,13 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.server.js" } ] }, { - "Route": "ComponentApp.styles.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -799,7 +925,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -807,7 +933,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -830,8 +956,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -844,7 +970,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -852,7 +978,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -878,17 +1004,17 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css.br" + "Value": "_framework/blazor.web.js.gz" } ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -903,7 +1029,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -911,7 +1037,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -938,12 +1064,12 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -958,7 +1084,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -966,7 +1092,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -996,13 +1122,13 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.web.js" } ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "ComponentApp.bundle.scp.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", "Selectors": [], "ResponseHeaders": [ { @@ -1013,6 +1139,10 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "br" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1028,6 +1158,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1038,8 +1172,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "ComponentApp.__fingerprint__.bundle.scp.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", "Selectors": [], "ResponseHeaders": [ { @@ -1050,6 +1184,10 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "br" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1065,6 +1203,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1078,14 +1220,20 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "ComponentApp.bundle.scp.css.br" } ] }, { "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", - "Selectors": [], + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -1095,6 +1243,10 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "br" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1107,9 +1259,17 @@ "Name": "ETag", "Value": "__etag__" }, + { + "Name": "ETag", + "Value": "__etag__" + }, { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1121,8 +1281,14 @@ }, { "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", - "Selectors": [], + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -1132,6 +1298,10 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "br" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1144,9 +1314,17 @@ "Name": "ETag", "Value": "__etag__" }, + { + "Name": "ETag", + "Value": "__etag__" + }, { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1163,6 +1341,982 @@ "Value": "ComponentApp.bundle.scp.css" } ] + }, + { + "Route": "ComponentApp.styles.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css.br" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js.br" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js.br" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] } ] } \ No newline at end of file diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DiscoversJsModulesBasedOnPatterns.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DiscoversJsModulesBasedOnPatterns.Build.staticwebassets.json index dc21cd899ee0..9eaf13263c29 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DiscoversJsModulesBasedOnPatterns.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DiscoversJsModulesBasedOnPatterns.Build.staticwebassets.json @@ -134,6 +134,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\Pages\\_content\\ComponentApp\\Pages\\Index.cshtml.js.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", "SourceId": "ComponentApp", @@ -175,6 +217,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -901,8 +985,8 @@ ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -913,13 +997,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -928,6 +1016,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -938,8 +1030,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -950,13 +1042,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -965,6 +1061,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -978,13 +1078,131 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -995,13 +1213,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -1010,6 +1232,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1020,8 +1246,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -1032,13 +1258,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -1047,6 +1277,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1060,7 +1294,453 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.web.js.gz" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" } ] } diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DoesNotFailToCompress_TwoAssetsWith_TheSameContent.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DoesNotFailToCompress_TwoAssetsWith_TheSameContent.Build.staticwebassets.json index 1cbee34c040c..63536c1d8faa 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DoesNotFailToCompress_TwoAssetsWith_TheSameContent.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DoesNotFailToCompress_TwoAssetsWith_TheSameContent.Build.staticwebassets.json @@ -58,6 +58,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\file.txt.gz", "SourceId": "ComponentApp", @@ -183,6 +225,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "wwwroot\\file.publish.txt" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -619,8 +703,8 @@ ] }, { - "Route": "file.txt.gz", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\file.txt.gz", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -641,7 +725,7 @@ }, { "Name": "Content-Type", - "Value": "text/plain" + "Value": "text/javascript" }, { "Name": "ETag", @@ -664,8 +748,8 @@ ] }, { - "Route": "file.txt.gz", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\file.txt.gz", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -674,7 +758,7 @@ }, { "Name": "Cache-Control", - "Value": "no-cache" + "Value": "max-age=31536000, immutable" }, { "Name": "Content-Encoding", @@ -686,7 +770,7 @@ }, { "Name": "Content-Type", - "Value": "text/plain" + "Value": "text/javascript" }, { "Name": "ETag", @@ -702,15 +786,23 @@ } ], "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, { "Name": "integrity", "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "file.txt", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\file.txt.gz", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [ { "Name": "Content-Encoding", @@ -737,7 +829,7 @@ }, { "Name": "Content-Type", - "Value": "text/plain" + "Value": "text/javascript" }, { "Name": "ETag", @@ -764,8 +856,8 @@ ] }, { - "Route": "file.txt", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\file.txt.gz", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [ { "Name": "Content-Encoding", @@ -780,7 +872,7 @@ }, { "Name": "Cache-Control", - "Value": "no-cache" + "Value": "max-age=31536000, immutable" }, { "Name": "Content-Encoding", @@ -792,7 +884,7 @@ }, { "Name": "Content-Type", - "Value": "text/plain" + "Value": "text/javascript" }, { "Name": "ETag", @@ -812,15 +904,23 @@ } ], "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, { "Name": "integrity", "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" } ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -831,13 +931,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -846,6 +950,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -856,8 +964,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -868,13 +976,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -883,6 +995,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -896,14 +1012,20 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.web.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", - "Selectors": [], + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -913,13 +1035,21 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "ETag", @@ -928,6 +1058,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -938,9 +1072,15 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", - "Selectors": [], + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -950,13 +1090,21 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "ETag", @@ -965,6 +1113,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -978,13 +1130,13 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.web.js" } ] }, { - "Route": "file.txt", - "AssetFile": "${ProjectPath}\\wwwroot\\file.build.txt", + "Route": "file.txt.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\file.txt.gz", "Selectors": [], "ResponseHeaders": [ { @@ -995,6 +1147,10 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1010,6 +1166,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1020,8 +1180,8 @@ ] }, { - "Route": "file.txt", - "AssetFile": "${ProjectPath}\\wwwroot\\file.publish.txt", + "Route": "file.txt.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\file.txt.gz", "Selectors": [], "ResponseHeaders": [ { @@ -1032,6 +1192,61 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/plain" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "file.txt", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\file.txt.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1044,9 +1259,17 @@ "Name": "ETag", "Value": "__etag__" }, + { + "Name": "ETag", + "Value": "__etag__" + }, { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1055,6 +1278,463 @@ "Value": "__integrity__" } ] + }, + { + "Route": "file.txt", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\file.txt.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/plain" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "file.txt", + "AssetFile": "${ProjectPath}\\wwwroot\\file.build.txt", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/plain" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "file.txt", + "AssetFile": "${ProjectPath}\\wwwroot\\file.publish.txt", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/plain" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] } ] } \ No newline at end of file diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DoesNotUpdateManifest_WhenHasNotChanged.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DoesNotUpdateManifest_WhenHasNotChanged.Build.staticwebassets.json index 6d6cea45277d..10ce4469cc28 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DoesNotUpdateManifest_WhenHasNotChanged.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_DoesNotUpdateManifest_WhenHasNotChanged.Build.staticwebassets.json @@ -50,6 +50,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", "SourceId": "ComponentApp", @@ -91,6 +133,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -527,8 +611,8 @@ ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -539,13 +623,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -554,6 +642,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -564,8 +656,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -576,13 +668,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -591,6 +687,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -604,13 +704,131 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -621,13 +839,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -636,6 +858,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -646,8 +872,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -658,13 +884,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -673,6 +903,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -686,7 +920,453 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.web.js.gz" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" } ] } diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_FingerprintsContent_WhenEnabled.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_FingerprintsContent_WhenEnabled.Build.staticwebassets.json index 6e87f32a82a5..620fb8fec978 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_FingerprintsContent_WhenEnabled.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_FingerprintsContent_WhenEnabled.Build.staticwebassets.json @@ -58,6 +58,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\css\\fingerprint-site#[.{fingerprint=__fingerprint__}]?.css.gz", "SourceId": "ComponentApp", @@ -141,6 +183,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "wwwroot\\css\\fingerprint-site.css" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -577,8 +661,8 @@ ] }, { - "Route": "css/fingerprint-site.css.gz", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\css\\fingerprint-site#[.{fingerprint=__fingerprint__}]?.css.gz", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -599,7 +683,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -622,8 +706,8 @@ ] }, { - "Route": "css/fingerprint-site.__fingerprint__.css.gz", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\css\\fingerprint-site#[.{fingerprint=__fingerprint__}]?.css.gz", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -644,7 +728,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -670,13 +754,13 @@ }, { "Name": "label", - "Value": "css/fingerprint-site.css.gz" + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "css/fingerprint-site.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\css\\fingerprint-site#[.{fingerprint=__fingerprint__}]?.css.gz", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [ { "Name": "Content-Encoding", @@ -703,7 +787,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -730,8 +814,8 @@ ] }, { - "Route": "css/fingerprint-site.__fingerprint__.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\css\\fingerprint-site#[.{fingerprint=__fingerprint__}]?.css.gz", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [ { "Name": "Content-Encoding", @@ -758,7 +842,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -788,13 +872,13 @@ }, { "Name": "label", - "Value": "css/fingerprint-site.css" + "Value": "_framework/blazor.server.js" } ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -805,13 +889,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -820,6 +908,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -830,8 +922,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -842,13 +934,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -857,6 +953,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -870,14 +970,20 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.web.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", - "Selectors": [], + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -887,13 +993,21 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "ETag", @@ -902,6 +1016,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -912,9 +1030,15 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", - "Selectors": [], + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -924,13 +1048,21 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "ETag", @@ -939,6 +1071,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -952,13 +1088,13 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.web.js" } ] }, { - "Route": "css/fingerprint-site.css", - "AssetFile": "${ProjectPath}\\wwwroot\\css\\fingerprint-site.css", + "Route": "css/fingerprint-site.css.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\css\\fingerprint-site#[.{fingerprint=__fingerprint__}]?.css.gz", "Selectors": [], "ResponseHeaders": [ { @@ -969,6 +1105,10 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -984,6 +1124,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -994,8 +1138,8 @@ ] }, { - "Route": "css/fingerprint-site.__fingerprint__.css", - "AssetFile": "${ProjectPath}\\wwwroot\\css\\fingerprint-site.css", + "Route": "css/fingerprint-site.__fingerprint__.css.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\css\\fingerprint-site#[.{fingerprint=__fingerprint__}]?.css.gz", "Selectors": [], "ResponseHeaders": [ { @@ -1006,6 +1150,10 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1021,6 +1169,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1034,7 +1186,535 @@ }, { "Name": "label", - "Value": "css/fingerprint-site.css" + "Value": "css/fingerprint-site.css.gz" + } + ] + }, + { + "Route": "css/fingerprint-site.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\css\\fingerprint-site#[.{fingerprint=__fingerprint__}]?.css.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "css/fingerprint-site.__fingerprint__.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\css\\fingerprint-site#[.{fingerprint=__fingerprint__}]?.css.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "css/fingerprint-site.css" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "css/fingerprint-site.css", + "AssetFile": "${ProjectPath}\\wwwroot\\css\\fingerprint-site.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "css/fingerprint-site.__fingerprint__.css", + "AssetFile": "${ProjectPath}\\wwwroot\\css\\fingerprint-site.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "css/fingerprint-site.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" } ] } diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_GeneratesJsonManifestAndCopiesItToOutputFolder.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_GeneratesJsonManifestAndCopiesItToOutputFolder.Build.staticwebassets.json index 6d6cea45277d..10ce4469cc28 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_GeneratesJsonManifestAndCopiesItToOutputFolder.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_GeneratesJsonManifestAndCopiesItToOutputFolder.Build.staticwebassets.json @@ -50,6 +50,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", "SourceId": "ComponentApp", @@ -91,6 +133,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -527,8 +611,8 @@ ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -539,13 +623,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -554,6 +642,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -564,8 +656,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -576,13 +668,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -591,6 +687,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -604,13 +704,131 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -621,13 +839,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -636,6 +858,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -646,8 +872,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -658,13 +884,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -673,6 +903,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -686,7 +920,453 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.web.js.gz" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" } ] } diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_UpdatesManifest_WhenFilesChange.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_UpdatesManifest_WhenFilesChange.Build.staticwebassets.json index 6d6cea45277d..10ce4469cc28 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_UpdatesManifest_WhenFilesChange.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_UpdatesManifest_WhenFilesChange.Build.staticwebassets.json @@ -50,6 +50,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", "SourceId": "ComponentApp", @@ -91,6 +133,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -527,8 +611,8 @@ ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -539,13 +623,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -554,6 +642,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -564,8 +656,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -576,13 +668,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -591,6 +687,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -604,13 +704,131 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -621,13 +839,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -636,6 +858,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -646,8 +872,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -658,13 +884,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -673,6 +903,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -686,7 +920,453 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.web.js.gz" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" } ] } diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_UpdatesManifest_WhenFilesChange_Updated.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_UpdatesManifest_WhenFilesChange_Updated.Build.staticwebassets.json index c7b4cfdbc6e0..cb6c125a0ed8 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_UpdatesManifest_WhenFilesChange_Updated.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_UpdatesManifest_WhenFilesChange_Updated.Build.staticwebassets.json @@ -58,6 +58,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\index.html.gz", "SourceId": "ComponentApp", @@ -141,6 +183,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "wwwroot\\index.html" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -577,8 +661,8 @@ ] }, { - "Route": "index.html.gz", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\index.html.gz", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -599,7 +683,7 @@ }, { "Name": "Content-Type", - "Value": "text/html" + "Value": "text/javascript" }, { "Name": "ETag", @@ -622,15 +706,9 @@ ] }, { - "Route": "index.html", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\index.html.gz", - "Selectors": [ - { - "Name": "Content-Encoding", - "Value": "gzip", - "Quality": "__quality__" - } - ], + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -638,7 +716,7 @@ }, { "Name": "Cache-Control", - "Value": "no-cache" + "Value": "max-age=31536000, immutable" }, { "Name": "Content-Encoding", @@ -650,11 +728,7 @@ }, { "Name": "Content-Type", - "Value": "text/html" - }, - { - "Name": "ETag", - "Value": "__etag__" + "Value": "text/javascript" }, { "Name": "ETag", @@ -670,16 +744,30 @@ } ], "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, { "Name": "integrity", "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", - "Selectors": [], + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -689,13 +777,21 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "ETag", @@ -704,6 +800,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -714,9 +814,15 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", - "Selectors": [], + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -726,13 +832,21 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "ETag", @@ -741,6 +855,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -754,13 +872,13 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.server.js" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -771,13 +889,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -786,6 +908,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -796,8 +922,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -808,13 +934,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -823,6 +953,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -836,14 +970,20 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.web.js.gz" } ] }, { - "Route": "index.html", - "AssetFile": "${ProjectPath}\\wwwroot\\index.html", - "Selectors": [], + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -853,13 +993,76 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/html" + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "ETag", @@ -868,12 +1071,489 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, { "Name": "integrity", "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] + }, + { + "Route": "index.html.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\index.html.gz", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/html" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "index.html", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\index.html.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/html" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "index.html", + "AssetFile": "${ProjectPath}\\wwwroot\\index.html", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/html" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" } ] } diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Clean_RemovesManifestFrom_BuildAndIntermediateOutput.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Clean_RemovesManifestFrom_BuildAndIntermediateOutput.Build.staticwebassets.json index 6d6cea45277d..10ce4469cc28 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Clean_RemovesManifestFrom_BuildAndIntermediateOutput.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Clean_RemovesManifestFrom_BuildAndIntermediateOutput.Build.staticwebassets.json @@ -50,6 +50,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", "SourceId": "ComponentApp", @@ -91,6 +133,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -527,8 +611,8 @@ ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -539,13 +623,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -554,6 +642,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -564,8 +656,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -576,13 +668,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -591,6 +687,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -604,13 +704,131 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -621,13 +839,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -636,6 +858,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -646,8 +872,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -658,13 +884,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -673,6 +903,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -686,7 +920,453 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.web.js.gz" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" } ] } diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_CreatesEndpointsForAssets.Publish.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_CreatesEndpointsForAssets.Publish.staticwebassets.json index 598bdd181a9b..316119881078 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_CreatesEndpointsForAssets.Publish.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_CreatesEndpointsForAssets.Publish.staticwebassets.json @@ -58,6 +58,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\app.js.gz", "SourceId": "ComponentApp", @@ -121,6 +163,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.br", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "br", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.br" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "br", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\app.js.br", "SourceId": "ComponentApp", @@ -204,6 +288,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "wwwroot\\app.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -640,8 +766,8 @@ ] }, { - "Route": "app.js.gz", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\app.js.gz", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -685,15 +811,9 @@ ] }, { - "Route": "app.js", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\app.js.gz", - "Selectors": [ - { - "Name": "Content-Encoding", - "Value": "gzip", - "Quality": "__quality__" - } - ], + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -701,7 +821,7 @@ }, { "Name": "Cache-Control", - "Value": "no-cache" + "Value": "max-age=31536000, immutable" }, { "Name": "Content-Encoding", @@ -719,10 +839,6 @@ "Name": "ETag", "Value": "__etag__" }, - { - "Name": "ETag", - "Value": "__etag__" - }, { "Name": "Last-Modified", "Value": "__last-modified__" @@ -733,16 +849,30 @@ } ], "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, { "Name": "integrity", "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", - "Selectors": [], + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -754,7 +884,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -762,7 +892,11 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "ETag", @@ -785,9 +919,15 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", - "Selectors": [], + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -799,7 +939,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -807,7 +947,11 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "ETag", @@ -833,20 +977,14 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css.br" + "Value": "_framework/blazor.server.js" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", - "Selectors": [ - { - "Name": "Content-Encoding", - "Value": "br", - "Quality": "__quality__" - } - ], + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -858,7 +996,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -866,11 +1004,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" - }, - { - "Name": "ETag", - "Value": "__etag__" + "Value": "text/javascript" }, { "Name": "ETag", @@ -893,15 +1027,9 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", - "Selectors": [ - { - "Name": "Content-Encoding", - "Value": "br", - "Quality": "__quality__" - } - ], + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -913,7 +1041,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -921,11 +1049,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" - }, - { - "Name": "ETag", - "Value": "__etag__" + "Value": "text/javascript" }, { "Name": "ETag", @@ -951,14 +1075,20 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.web.js.gz" } ] }, { - "Route": "ComponentApp.styles.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", - "Selectors": [], + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -970,7 +1100,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -978,7 +1108,11 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "ETag", @@ -1001,9 +1135,15 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", - "Selectors": [], + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -1015,7 +1155,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -1023,7 +1163,11 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "ETag", @@ -1049,20 +1193,14 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css.br" + "Value": "_framework/blazor.web.js" } ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", - "Selectors": [ - { - "Name": "Content-Encoding", - "Value": "br", - "Quality": "__quality__" - } - ], + "Route": "app.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\app.js.gz", + "Selectors": [], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -1074,7 +1212,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -1082,15 +1220,804 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", "Value": "__etag__" }, { - "Name": "ETag", - "Value": "__etag__" + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "app.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\app.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css.br" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "ComponentApp.styles.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css.br" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js.br" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "Last-Modified", @@ -1102,15 +2029,78 @@ } ], "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, { "Name": "integrity", "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js.br" } ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", "Selectors": [ { "Name": "Content-Encoding", @@ -1137,7 +2127,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -1167,7 +2157,7 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.web.js" } ] }, @@ -1471,6 +2461,170 @@ "Value": "__integrity__" } ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] } ] } \ No newline at end of file diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_CreatesEndpointsForAssets_BuildAndPublish_Assets.Publish.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_CreatesEndpointsForAssets_BuildAndPublish_Assets.Publish.staticwebassets.json index 09bd5c139562..a24b70400f08 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_CreatesEndpointsForAssets_BuildAndPublish_Assets.Publish.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_CreatesEndpointsForAssets_BuildAndPublish_Assets.Publish.staticwebassets.json @@ -58,6 +58,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\app.js.gz", "SourceId": "ComponentApp", @@ -121,6 +163,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.br", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "br", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.br" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "br", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\app.js.br", "SourceId": "ComponentApp", @@ -204,6 +288,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "wwwroot\\app.publish.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -640,8 +766,8 @@ ] }, { - "Route": "app.js.gz", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\app.js.gz", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -685,15 +811,9 @@ ] }, { - "Route": "app.js", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\app.js.gz", - "Selectors": [ - { - "Name": "Content-Encoding", - "Value": "gzip", - "Quality": "__quality__" - } - ], + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -701,7 +821,7 @@ }, { "Name": "Cache-Control", - "Value": "no-cache" + "Value": "max-age=31536000, immutable" }, { "Name": "Content-Encoding", @@ -719,10 +839,6 @@ "Name": "ETag", "Value": "__etag__" }, - { - "Name": "ETag", - "Value": "__etag__" - }, { "Name": "Last-Modified", "Value": "__last-modified__" @@ -733,16 +849,30 @@ } ], "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, { "Name": "integrity", "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", - "Selectors": [], + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -754,7 +884,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -762,7 +892,11 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "ETag", @@ -785,9 +919,15 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", - "Selectors": [], + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -799,7 +939,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -807,7 +947,11 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "ETag", @@ -833,20 +977,14 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css.br" + "Value": "_framework/blazor.server.js" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", - "Selectors": [ - { - "Name": "Content-Encoding", - "Value": "br", - "Quality": "__quality__" - } - ], + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -858,7 +996,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -866,11 +1004,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" - }, - { - "Name": "ETag", - "Value": "__etag__" + "Value": "text/javascript" }, { "Name": "ETag", @@ -893,15 +1027,9 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", - "Selectors": [ - { - "Name": "Content-Encoding", - "Value": "br", - "Quality": "__quality__" - } - ], + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -913,7 +1041,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -921,11 +1049,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" - }, - { - "Name": "ETag", - "Value": "__etag__" + "Value": "text/javascript" }, { "Name": "ETag", @@ -951,14 +1075,20 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.web.js.gz" } ] }, { - "Route": "ComponentApp.styles.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", - "Selectors": [], + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -970,7 +1100,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -978,7 +1108,11 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "ETag", @@ -1001,9 +1135,15 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", - "Selectors": [], + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -1015,7 +1155,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -1023,7 +1163,11 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "ETag", @@ -1049,20 +1193,14 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css.br" + "Value": "_framework/blazor.web.js" } ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", - "Selectors": [ - { - "Name": "Content-Encoding", - "Value": "br", - "Quality": "__quality__" - } - ], + "Route": "app.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\app.js.gz", + "Selectors": [], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -1074,7 +1212,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -1082,15 +1220,804 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", "Value": "__etag__" }, { - "Name": "ETag", - "Value": "__etag__" + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "app.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\app.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css.br" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "ComponentApp.styles.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css.br" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js.br" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "Last-Modified", @@ -1102,15 +2029,78 @@ } ], "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, { "Name": "integrity", "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js.br" } ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", "Selectors": [ { "Name": "Content-Encoding", @@ -1137,7 +2127,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -1167,7 +2157,7 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.web.js" } ] }, @@ -1471,6 +2461,170 @@ "Value": "__integrity__" } ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] } ] } \ No newline at end of file diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_GeneratesPublishJsonManifestAndCopiesPublishAssets.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_GeneratesPublishJsonManifestAndCopiesPublishAssets.Build.staticwebassets.json index 6d6cea45277d..10ce4469cc28 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_GeneratesPublishJsonManifestAndCopiesPublishAssets.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_GeneratesPublishJsonManifestAndCopiesPublishAssets.Build.staticwebassets.json @@ -50,6 +50,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", "SourceId": "ComponentApp", @@ -91,6 +133,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -527,8 +611,8 @@ ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -539,13 +623,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -554,6 +642,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -564,8 +656,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -576,13 +668,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -591,6 +687,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -604,13 +704,131 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -621,13 +839,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -636,6 +858,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -646,8 +872,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -658,13 +884,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -673,6 +903,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -686,7 +920,453 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.web.js.gz" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" } ] } diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.files.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.files.json index 8fe45cab05c6..491743598308 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.files.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.files.json @@ -2,6 +2,12 @@ "${OutputPath}\\wwwroot\\ComponentApp.styles.css", "${OutputPath}\\wwwroot\\ComponentApp.styles.css.br", "${OutputPath}\\wwwroot\\ComponentApp.styles.css.gz", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js.br", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js.gz", + "${OutputPath}\\wwwroot\\_framework\\blazor.web.js", + "${OutputPath}\\wwwroot\\_framework\\blazor.web.js.br", + "${OutputPath}\\wwwroot\\_framework\\blazor.web.js.gz", "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.gz", "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz", "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", @@ -10,5 +16,11 @@ "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", "${OutputPath}\\wwwroot\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", "${OutputPath}\\wwwroot\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz", - "${OutputPath}\\wwwroot\\ComponentApp#[.{fingerprint}]?.styles.css" + "${OutputPath}\\wwwroot\\ComponentApp#[.{fingerprint}]?.styles.css", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js.br", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js.gz", + "${OutputPath}\\wwwroot\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "${OutputPath}\\wwwroot\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "${OutputPath}\\wwwroot\\_framework\\blazor.web#[.{fingerprint}]?.js" ] \ No newline at end of file diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.staticwebassets.json index 109d70f6bf4b..b3b9db6e7320 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.staticwebassets.json @@ -50,6 +50,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", "SourceId": "ComponentApp", @@ -92,6 +134,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.br", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "br", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.br" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "br", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", "SourceId": "ComponentApp", @@ -133,6 +217,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -569,8 +695,8 @@ ] }, { - "Route": "ComponentApp.bundle.scp.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -583,7 +709,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -591,7 +717,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -614,8 +740,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -628,7 +754,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -636,7 +762,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -662,17 +788,17 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css.br" + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -687,7 +813,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -695,7 +821,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -722,12 +848,12 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -742,7 +868,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -750,7 +876,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -780,13 +906,13 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.server.js" } ] }, { - "Route": "ComponentApp.styles.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -799,7 +925,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -807,7 +933,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -830,8 +956,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -844,7 +970,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -852,7 +978,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -878,17 +1004,17 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css.br" + "Value": "_framework/blazor.web.js.gz" } ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -903,7 +1029,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -911,7 +1037,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -938,12 +1064,12 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -958,7 +1084,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -966,7 +1092,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -996,13 +1122,13 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.web.js" } ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "ComponentApp.bundle.scp.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", "Selectors": [], "ResponseHeaders": [ { @@ -1013,6 +1139,10 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "br" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1028,6 +1158,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1038,8 +1172,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "ComponentApp.__fingerprint__.bundle.scp.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", "Selectors": [], "ResponseHeaders": [ { @@ -1050,6 +1184,10 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "br" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1065,6 +1203,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1078,14 +1220,20 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "ComponentApp.bundle.scp.css.br" } ] }, { "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", - "Selectors": [], + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -1095,6 +1243,10 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "br" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1107,9 +1259,17 @@ "Name": "ETag", "Value": "__etag__" }, + { + "Name": "ETag", + "Value": "__etag__" + }, { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1121,8 +1281,14 @@ }, { "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", - "Selectors": [], + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -1132,6 +1298,10 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "br" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1144,9 +1314,17 @@ "Name": "ETag", "Value": "__etag__" }, + { + "Name": "ETag", + "Value": "__etag__" + }, { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1163,6 +1341,982 @@ "Value": "ComponentApp.bundle.scp.css" } ] + }, + { + "Route": "ComponentApp.styles.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css.br" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js.br" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js.br" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] } ] } \ No newline at end of file diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_NoBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_NoBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Build.staticwebassets.json index 6d6cea45277d..10ce4469cc28 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_NoBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_NoBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Build.staticwebassets.json @@ -50,6 +50,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", "SourceId": "ComponentApp", @@ -91,6 +133,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -527,8 +611,8 @@ ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -539,13 +623,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -554,6 +642,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -564,8 +656,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -576,13 +668,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -591,6 +687,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -604,13 +704,131 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -621,13 +839,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -636,6 +858,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -646,8 +872,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -658,13 +884,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -673,6 +903,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -686,7 +920,453 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.web.js.gz" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" } ] } diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_NoBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.files.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_NoBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.files.json index b7d5099f9332..9d42d40958c9 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_NoBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.files.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_NoBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.files.json @@ -7,5 +7,11 @@ "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", "${OutputPath}\\wwwroot\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", "${OutputPath}\\wwwroot\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz", - "${OutputPath}\\wwwroot\\ComponentApp#[.{fingerprint}]?.styles.css" + "${OutputPath}\\wwwroot\\ComponentApp#[.{fingerprint}]?.styles.css", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js.br", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js.gz", + "${OutputPath}\\wwwroot\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "${OutputPath}\\wwwroot\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "${OutputPath}\\wwwroot\\_framework\\blazor.web#[.{fingerprint}]?.js" ] \ No newline at end of file diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_NoBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_NoBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.staticwebassets.json index 109d70f6bf4b..b3b9db6e7320 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_NoBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_NoBuild_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.staticwebassets.json @@ -50,6 +50,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", "SourceId": "ComponentApp", @@ -92,6 +134,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.br", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "br", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.br" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "br", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", "SourceId": "ComponentApp", @@ -133,6 +217,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -569,8 +695,8 @@ ] }, { - "Route": "ComponentApp.bundle.scp.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -583,7 +709,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -591,7 +717,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -614,8 +740,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -628,7 +754,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -636,7 +762,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -662,17 +788,17 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css.br" + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -687,7 +813,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -695,7 +821,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -722,12 +848,12 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -742,7 +868,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -750,7 +876,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -780,13 +906,13 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.server.js" } ] }, { - "Route": "ComponentApp.styles.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -799,7 +925,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -807,7 +933,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -830,8 +956,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -844,7 +970,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -852,7 +978,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -878,17 +1004,17 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css.br" + "Value": "_framework/blazor.web.js.gz" } ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -903,7 +1029,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -911,7 +1037,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -938,12 +1064,12 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -958,7 +1084,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -966,7 +1092,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -996,13 +1122,13 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.web.js" } ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "ComponentApp.bundle.scp.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", "Selectors": [], "ResponseHeaders": [ { @@ -1013,6 +1139,10 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "br" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1028,6 +1158,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1038,8 +1172,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "ComponentApp.__fingerprint__.bundle.scp.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", "Selectors": [], "ResponseHeaders": [ { @@ -1050,6 +1184,10 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "br" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1065,6 +1203,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1078,14 +1220,20 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "ComponentApp.bundle.scp.css.br" } ] }, { "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", - "Selectors": [], + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -1095,6 +1243,10 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "br" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1107,9 +1259,17 @@ "Name": "ETag", "Value": "__etag__" }, + { + "Name": "ETag", + "Value": "__etag__" + }, { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1121,8 +1281,14 @@ }, { "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", - "Selectors": [], + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -1132,6 +1298,10 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "br" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1144,9 +1314,17 @@ "Name": "ETag", "Value": "__etag__" }, + { + "Name": "ETag", + "Value": "__etag__" + }, { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1163,6 +1341,982 @@ "Value": "ComponentApp.bundle.scp.css" } ] + }, + { + "Route": "ComponentApp.styles.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css.br" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js.br" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js.br" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] } ] } \ No newline at end of file diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishSingleFile_GeneratesPublishJsonManifestAndCopiesPublishAssets.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishSingleFile_GeneratesPublishJsonManifestAndCopiesPublishAssets.Build.staticwebassets.json index 443ea8836b15..ed707009ccca 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishSingleFile_GeneratesPublishJsonManifestAndCopiesPublishAssets.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishSingleFile_GeneratesPublishJsonManifestAndCopiesPublishAssets.Build.staticwebassets.json @@ -50,6 +50,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\bundle\\ComponentApp.styles.css", "SourceId": "ComponentApp", @@ -91,6 +133,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -527,8 +611,8 @@ ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -539,13 +623,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -554,6 +642,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -564,8 +656,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -576,13 +668,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -591,6 +687,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -604,13 +704,131 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -621,13 +839,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -636,6 +858,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -646,8 +872,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -658,13 +884,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -673,6 +903,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -686,7 +920,453 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.web.js.gz" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" } ] } diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishSingleFile_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.files.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishSingleFile_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.files.json index 3f6ff18b3b3c..d4300d7b0f03 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishSingleFile_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.files.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishSingleFile_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.files.json @@ -7,5 +7,11 @@ "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", "${OutputPath}\\wwwroot\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", "${OutputPath}\\wwwroot\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz", - "${OutputPath}\\wwwroot\\ComponentApp#[.{fingerprint}]?.styles.css" + "${OutputPath}\\wwwroot\\ComponentApp#[.{fingerprint}]?.styles.css", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js.br", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js.gz", + "${OutputPath}\\wwwroot\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "${OutputPath}\\wwwroot\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "${OutputPath}\\wwwroot\\_framework\\blazor.web#[.{fingerprint}]?.js" ] \ No newline at end of file diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishSingleFile_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishSingleFile_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.staticwebassets.json index 618e5a3cf765..d1cc84bec90a 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishSingleFile_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishSingleFile_GeneratesPublishJsonManifestAndCopiesPublishAssets.Publish.staticwebassets.json @@ -50,6 +50,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", "SourceId": "ComponentApp", @@ -92,6 +134,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.br", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "br", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.br" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "br", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\bundle\\ComponentApp.styles.css", "SourceId": "ComponentApp", @@ -133,6 +217,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -569,8 +695,8 @@ ] }, { - "Route": "ComponentApp.bundle.scp.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -583,7 +709,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -591,7 +717,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -614,8 +740,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -628,7 +754,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -636,7 +762,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -662,17 +788,17 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css.br" + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -687,7 +813,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -695,7 +821,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -722,12 +848,12 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -742,7 +868,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -750,7 +876,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -780,13 +906,13 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.server.js" } ] }, { - "Route": "ComponentApp.styles.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -799,7 +925,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -807,7 +933,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -830,8 +956,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -844,7 +970,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -852,7 +978,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -878,17 +1004,17 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css.br" + "Value": "_framework/blazor.web.js.gz" } ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -903,7 +1029,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -911,7 +1037,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -938,12 +1064,12 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -958,7 +1084,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -966,7 +1092,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -996,13 +1122,13 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.web.js" } ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "ComponentApp.bundle.scp.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", "Selectors": [], "ResponseHeaders": [ { @@ -1013,6 +1139,10 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "br" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1028,6 +1158,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1038,8 +1172,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "ComponentApp.__fingerprint__.bundle.scp.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", "Selectors": [], "ResponseHeaders": [ { @@ -1050,6 +1184,10 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "br" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1065,6 +1203,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1078,14 +1220,20 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "ComponentApp.bundle.scp.css.br" } ] }, { "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", - "Selectors": [], + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -1095,6 +1243,10 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "br" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1107,9 +1259,17 @@ "Name": "ETag", "Value": "__etag__" }, + { + "Name": "ETag", + "Value": "__etag__" + }, { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1121,8 +1281,14 @@ }, { "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", - "Selectors": [], + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -1132,6 +1298,10 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "br" + }, { "Name": "Content-Length", "Value": "__content-length__" @@ -1144,9 +1314,17 @@ "Name": "ETag", "Value": "__etag__" }, + { + "Name": "ETag", + "Value": "__etag__" + }, { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -1163,6 +1341,982 @@ "Value": "ComponentApp.bundle.scp.css" } ] + }, + { + "Route": "ComponentApp.styles.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css.br" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js.br" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js.br" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\${Rid}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] } ] } \ No newline at end of file diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishesJsModuleBundleBundleToTheRightLocation.Publish.files.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishesJsModuleBundleBundleToTheRightLocation.Publish.files.json index 3530c7e064ce..2e8855bb22d7 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishesJsModuleBundleBundleToTheRightLocation.Publish.files.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishesJsModuleBundleBundleToTheRightLocation.Publish.files.json @@ -8,6 +8,12 @@ "${OutputPath}\\wwwroot\\ComponentApp.styles.css", "${OutputPath}\\wwwroot\\ComponentApp.styles.css.br", "${OutputPath}\\wwwroot\\ComponentApp.styles.css.gz", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js.br", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js.gz", + "${OutputPath}\\wwwroot\\_framework\\blazor.web.js", + "${OutputPath}\\wwwroot\\_framework\\blazor.web.js.br", + "${OutputPath}\\wwwroot\\_framework\\blazor.web.js.gz", "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.gz", "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz", "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", @@ -25,5 +31,11 @@ "${OutputPath}\\wwwroot\\ComponentApp#[.{fingerprint}]?.styles.css", "${OutputPath}\\wwwroot\\ComponentApp.modules.json", "${OutputPath}\\wwwroot\\ComponentApp.modules.json.br", - "${OutputPath}\\wwwroot\\ComponentApp.modules.json.gz" + "${OutputPath}\\wwwroot\\ComponentApp.modules.json.gz", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js.br", + "${OutputPath}\\wwwroot\\_framework\\blazor.server.js.gz", + "${OutputPath}\\wwwroot\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "${OutputPath}\\wwwroot\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "${OutputPath}\\wwwroot\\_framework\\blazor.web#[.{fingerprint}]?.js" ] \ No newline at end of file diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishesJsModuleBundleBundleToTheRightLocation.Publish.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishesJsModuleBundleBundleToTheRightLocation.Publish.staticwebassets.json index 6703bf444562..c21f8c461dab 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishesJsModuleBundleBundleToTheRightLocation.Publish.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Publish_PublishesJsModuleBundleBundleToTheRightLocation.Publish.staticwebassets.json @@ -79,6 +79,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", "SourceId": "ComponentApp", @@ -184,6 +226,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\jsmodules\\_content\\ComponentApp\\ComponentApp.modules.json.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.br", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "br", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.br" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "br", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\jsmodules\\jsmodules.publish.manifest.json", "SourceId": "ComponentApp", @@ -267,6 +351,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "wwwroot\\ComponentApp.lib.module.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -935,8 +1061,8 @@ ] }, { - "Route": "ComponentApp.bundle.scp.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -949,7 +1075,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -957,7 +1083,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -980,8 +1106,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -994,7 +1120,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -1002,7 +1128,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -1028,17 +1154,17 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css.br" + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -1053,7 +1179,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -1061,7 +1187,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -1088,12 +1214,12 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -1108,7 +1234,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -1116,7 +1242,7 @@ }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -1146,13 +1272,13 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.server.js" } ] }, { - "Route": "ComponentApp.lib.module.js.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.lib.module.js.br", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -1165,7 +1291,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -1196,8 +1322,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.lib.module.js.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.lib.module.js.br", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -1210,7 +1336,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -1244,17 +1370,17 @@ }, { "Name": "label", - "Value": "ComponentApp.lib.module.js.br" + "Value": "_framework/blazor.web.js.gz" } ] }, { - "Route": "ComponentApp.lib.module.js", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.lib.module.js.br", + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -1269,7 +1395,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -1297,27 +1423,19 @@ } ], "EndpointProperties": [ - { - "Name": "dependency-group", - "Value": "js-initializer" - }, { "Name": "integrity", "Value": "__integrity__" - }, - { - "Name": "script-type", - "Value": "module" } ] }, { - "Route": "ComponentApp.__fingerprint__.lib.module.js", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.lib.module.js.br", + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [ { "Name": "Content-Encoding", - "Value": "br", + "Value": "gzip", "Quality": "__quality__" } ], @@ -1332,7 +1450,7 @@ }, { "Name": "Content-Encoding", - "Value": "br" + "Value": "gzip" }, { "Name": "Content-Length", @@ -1360,10 +1478,6 @@ } ], "EndpointProperties": [ - { - "Name": "dependency-group", - "Value": "js-initializer" - }, { "Name": "fingerprint", "Value": "__fingerprint__" @@ -1374,17 +1488,13 @@ }, { "Name": "label", - "Value": "ComponentApp.lib.module.js" - }, - { - "Name": "script-type", - "Value": "module" + "Value": "_framework/blazor.web.js" } ] }, { - "Route": "ComponentApp.styles.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "ComponentApp.bundle.scp.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", "Selectors": [], "ResponseHeaders": [ { @@ -1428,8 +1538,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "ComponentApp.__fingerprint__.bundle.scp.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", "Selectors": [], "ResponseHeaders": [ { @@ -1476,13 +1586,13 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css.br" + "Value": "ComponentApp.bundle.scp.css.br" } ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", "Selectors": [ { "Name": "Content-Encoding", @@ -1536,8 +1646,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.br", "Selectors": [ { "Name": "Content-Encoding", @@ -1594,13 +1704,13 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "ComponentApp.bundle.scp.css" } ] }, { - "Route": "ComponentApp.modules.json.br", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp.modules.json.br", + "Route": "ComponentApp.lib.module.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.lib.module.js.br", "Selectors": [], "ResponseHeaders": [ { @@ -1621,7 +1731,7 @@ }, { "Name": "Content-Type", - "Value": "application/json" + "Value": "text/javascript" }, { "Name": "ETag", @@ -1644,15 +1754,9 @@ ] }, { - "Route": "ComponentApp.modules.json", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp.modules.json.br", - "Selectors": [ - { - "Name": "Content-Encoding", - "Value": "br", - "Quality": "__quality__" - } - ], + "Route": "ComponentApp.__fingerprint__.lib.module.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.lib.module.js.br", + "Selectors": [], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -1660,7 +1764,7 @@ }, { "Name": "Cache-Control", - "Value": "no-cache" + "Value": "max-age=31536000, immutable" }, { "Name": "Content-Encoding", @@ -1672,11 +1776,7 @@ }, { "Name": "Content-Type", - "Value": "application/json" - }, - { - "Name": "ETag", - "Value": "__etag__" + "Value": "text/javascript" }, { "Name": "ETag", @@ -1692,16 +1792,30 @@ } ], "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, { "Name": "integrity", "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.lib.module.js.br" } ] }, { - "Route": "ComponentApp.modules.json.gz", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp.modules.json.gz", - "Selectors": [], + "Route": "ComponentApp.lib.module.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.lib.module.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], "ResponseHeaders": [ { "Name": "Accept-Ranges", @@ -1713,7 +1827,7 @@ }, { "Name": "Content-Encoding", - "Value": "gzip" + "Value": "br" }, { "Name": "Content-Length", @@ -1721,7 +1835,11 @@ }, { "Name": "Content-Type", - "Value": "application/json" + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" }, { "Name": "ETag", @@ -1737,19 +1855,27 @@ } ], "EndpointProperties": [ + { + "Name": "dependency-group", + "Value": "js-initializer" + }, { "Name": "integrity", "Value": "__integrity__" + }, + { + "Name": "script-type", + "Value": "module" } ] }, { - "Route": "ComponentApp.modules.json", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp.modules.json.gz", + "Route": "ComponentApp.__fingerprint__.lib.module.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]!.lib.module.js.br", "Selectors": [ { "Name": "Content-Encoding", - "Value": "gzip", + "Value": "br", "Quality": "__quality__" } ], @@ -1760,7 +1886,439 @@ }, { "Name": "Cache-Control", - "Value": "no-cache" + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "dependency-group", + "Value": "js-initializer" + }, + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.lib.module.js" + }, + { + "Name": "script-type", + "Value": "module" + } + ] + }, + { + "Route": "ComponentApp.styles.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css.br" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.modules.json.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp.modules.json.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "application/json" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.modules.json", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp.modules.json.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "application/json" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.modules.json.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp.modules.json.gz", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "application/json" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.modules.json", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\ComponentApp.modules.json.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" }, { "Name": "Content-Encoding", @@ -1772,7 +2330,431 @@ }, { "Name": "Content-Type", - "Value": "application/json" + "Value": "application/json" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js.br" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.server.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js.br", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js.br" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\publish\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.br", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "br", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "br" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" }, { "Name": "ETag", @@ -1792,9 +2774,17 @@ } ], "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, { "Name": "integrity", "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" } ] }, @@ -2096,6 +3086,170 @@ "Value": "module" } ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] } ] } \ No newline at end of file diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Rebuild_RegeneratesJsonManifestAndCopiesItToOutputFolder.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Rebuild_RegeneratesJsonManifestAndCopiesItToOutputFolder.Build.staticwebassets.json index 6d6cea45277d..10ce4469cc28 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Rebuild_RegeneratesJsonManifestAndCopiesItToOutputFolder.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Rebuild_RegeneratesJsonManifestAndCopiesItToOutputFolder.Build.staticwebassets.json @@ -50,6 +50,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", "SourceId": "ComponentApp", @@ -91,6 +133,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -527,8 +611,8 @@ ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -539,13 +623,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -554,6 +642,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -564,8 +656,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -576,13 +668,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -591,6 +687,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -604,13 +704,131 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -621,13 +839,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -636,6 +858,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -646,8 +872,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -658,13 +884,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -673,6 +903,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -686,7 +920,453 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.web.js.gz" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" } ] } diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Rebuild_RegeneratesJsonManifestAndCopiesItToOutputFolder_Rebuild.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Rebuild_RegeneratesJsonManifestAndCopiesItToOutputFolder_Rebuild.Build.staticwebassets.json index 6d6cea45277d..10ce4469cc28 100644 --- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Rebuild_RegeneratesJsonManifestAndCopiesItToOutputFolder_Rebuild.Build.staticwebassets.json +++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Rebuild_RegeneratesJsonManifestAndCopiesItToOutputFolder_Rebuild.Build.staticwebassets.json @@ -50,6 +50,48 @@ "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\ComponentApp\\ComponentApp#[.{fingerprint=__fingerprint__}]?.styles.css.gz" }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.server.js.gz" + }, + { + "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Alternative", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "AssetTraitName": "Content-Encoding", + "AssetTraitValue": "gzip", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz" + }, { "Identity": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", "SourceId": "ComponentApp", @@ -91,6 +133,48 @@ "CopyToOutputDirectory": "Never", "CopyToPublishDirectory": "PreserveNewest", "OriginalItemSpec": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.server.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.server.js" + }, + { + "Identity": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "SourceId": "ComponentApp", + "SourceType": "Discovered", + "ContentRoot": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\", + "BasePath": "_content/ComponentApp", + "RelativePath": "_framework/blazor.web#[.{fingerprint}]?.js", + "AssetKind": "All", + "AssetMode": "CurrentProject", + "AssetRole": "Primary", + "AssetMergeBehavior": "", + "AssetMergeSource": "", + "RelatedAsset": "", + "AssetTraitName": "", + "AssetTraitValue": "", + "Fingerprint": "__fingerprint__", + "Integrity": "__integrity__", + "CopyToOutputDirectory": "Never", + "CopyToPublishDirectory": "PreserveNewest", + "OriginalItemSpec": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\build\\..\\_framework\\blazor.web.js" } ], "Endpoints": [ @@ -527,8 +611,8 @@ ] }, { - "Route": "ComponentApp.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -539,13 +623,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -554,6 +642,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -564,8 +656,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.styles.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Route": "_framework/blazor.server.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -576,13 +668,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -591,6 +687,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -604,13 +704,131 @@ }, { "Name": "label", - "Value": "ComponentApp.styles.css" + "Value": "_framework/blazor.server.js.gz" } ] }, { - "Route": "ComponentApp.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.server.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -621,13 +839,17 @@ "Name": "Cache-Control", "Value": "no-cache" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -636,6 +858,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -646,8 +872,8 @@ ] }, { - "Route": "ComponentApp.__fingerprint__.bundle.scp.css", - "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Route": "_framework/blazor.web.js.gz", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", "Selectors": [], "ResponseHeaders": [ { @@ -658,13 +884,17 @@ "Name": "Cache-Control", "Value": "max-age=31536000, immutable" }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, { "Name": "Content-Length", "Value": "__content-length__" }, { "Name": "Content-Type", - "Value": "text/css" + "Value": "text/javascript" }, { "Name": "ETag", @@ -673,6 +903,10 @@ { "Name": "Last-Modified", "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" } ], "EndpointProperties": [ @@ -686,7 +920,453 @@ }, { "Name": "label", - "Value": "ComponentApp.bundle.scp.css" + "Value": "_framework/blazor.web.js.gz" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\compressed\\_content\\ComponentApp\\_framework\\blazor.web#[.{fingerprint=__fingerprint__}]?.js.gz", + "Selectors": [ + { + "Name": "Content-Encoding", + "Value": "gzip", + "Quality": "__quality__" + } + ], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Encoding", + "Value": "gzip" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + }, + { + "Name": "Vary", + "Value": "Content-Encoding" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" + } + ] + }, + { + "Route": "ComponentApp.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.styles.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\ComponentApp.styles.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.styles.css" + } + ] + }, + { + "Route": "ComponentApp.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "ComponentApp.__fingerprint__.bundle.scp.css", + "AssetFile": "${ProjectPath}\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ComponentApp.bundle.scp.css", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/css" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "ComponentApp.bundle.scp.css" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.server.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.server.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.server.js" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "no-cache" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "integrity", + "Value": "__integrity__" + } + ] + }, + { + "Route": "_framework/blazor.web.js", + "AssetFile": "${RestorePath}\\microsoft.aspnetcore.app.internal.assets\\${PackageVersion}\\_framework\\blazor.web.js", + "Selectors": [], + "ResponseHeaders": [ + { + "Name": "Accept-Ranges", + "Value": "bytes" + }, + { + "Name": "Cache-Control", + "Value": "max-age=31536000, immutable" + }, + { + "Name": "Content-Length", + "Value": "__content-length__" + }, + { + "Name": "Content-Type", + "Value": "text/javascript" + }, + { + "Name": "ETag", + "Value": "__etag__" + }, + { + "Name": "Last-Modified", + "Value": "__last-modified__" + } + ], + "EndpointProperties": [ + { + "Name": "fingerprint", + "Value": "__fingerprint__" + }, + { + "Name": "integrity", + "Value": "__integrity__" + }, + { + "Name": "label", + "Value": "_framework/blazor.web.js" } ] } diff --git a/test/Microsoft.NET.TestFramework/Commands/TestCommand.cs b/test/Microsoft.NET.TestFramework/Commands/TestCommand.cs index 96d555bb293f..bd8efafeb284 100644 --- a/test/Microsoft.NET.TestFramework/Commands/TestCommand.cs +++ b/test/Microsoft.NET.TestFramework/Commands/TestCommand.cs @@ -61,6 +61,12 @@ public TestCommand WithTraceOutput() return this; } + public TestCommand WithEnableTestingPlatform() + { + WithEnvironmentVariable("DOTNET_CLI_TESTINGPLATFORM_ENABLE", "1"); + return this; + } + private SdkCommandSpec CreateCommandSpec(IEnumerable args) { var commandSpec = CreateCommand(args); diff --git a/test/Microsoft.NET.TestFramework/FileConstants.cs b/test/Microsoft.NET.TestFramework/FileConstants.cs index 54902a4e0b5d..c5029dfb8eee 100644 --- a/test/Microsoft.NET.TestFramework/FileConstants.cs +++ b/test/Microsoft.NET.TestFramework/FileConstants.cs @@ -9,8 +9,5 @@ public static class FileConstants public static readonly string DynamicLibSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".dll" : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? ".dylib" : ".so"; - public static readonly string? UserProfileFolder = Environment.GetEnvironmentVariable( - RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? - "USERPROFILE" : "HOME"); } } diff --git a/test/Microsoft.NET.TestFramework/TestAsset.cs b/test/Microsoft.NET.TestFramework/TestAsset.cs index 3c74e3d6088d..aedd70956111 100644 --- a/test/Microsoft.NET.TestFramework/TestAsset.cs +++ b/test/Microsoft.NET.TestFramework/TestAsset.cs @@ -148,14 +148,13 @@ public TestAsset ReplacePackageVersionVariable(string targetName, string targetV .Where(va => va is not null && va.Value.Equals($"$({targetName})", StringComparison.OrdinalIgnoreCase)); foreach (var versionAttribute in packageReferencesToUpdate) { - if(versionAttribute is not null) + if (versionAttribute is not null) { versionAttribute.Value = targetValue; } } } } - }); } @@ -271,6 +270,32 @@ public TestAsset Restore(ITestOutputHelper log, string relativePath = "", params return this; } + public string ReadMSTestVersionFromProps(string propsFilePath) + { + XDocument doc = XDocument.Load(propsFilePath); + XElement? msTestVersionElement = doc.Descendants("MSTestVersion").FirstOrDefault(); + return msTestVersionElement?.Value ?? throw new InvalidOperationException("MSTestVersion not found in Version.props"); + } + + public void UpdateProjectFileWithMSTestVersion(string projectPath, string msTestVersion) + { + if (projectPath is null) + { + throw new FileNotFoundException("No .csproj file found in the project directory."); + } + + XDocument csprojDoc = XDocument.Load(projectPath); + XElement? projectElement = csprojDoc.Element("Project"); + if (projectElement == null) + { + throw new InvalidOperationException("Invalid .csproj file format."); + } + + projectElement.SetAttributeValue("Sdk", $"MSTest.Sdk/{msTestVersion}"); + + csprojDoc.Save(projectPath); + } + private bool IsBinOrObjFolder(string directory) { var binFolder = $"{System.IO.Path.DirectorySeparatorChar}bin"; diff --git a/test/Microsoft.NET.TestFramework/TestingConstants.cs b/test/Microsoft.NET.TestFramework/TestingConstants.cs new file mode 100644 index 000000000000..bd11f4d832dd --- /dev/null +++ b/test/Microsoft.NET.TestFramework/TestingConstants.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.NET.TestFramework +{ + internal static class TestingConstants + { + public const string Debug = "Debug"; + public const string Release = "Release"; + + public const string Failed = "failed"; + public const string Passed = "passed"; + } +} diff --git a/test/Microsoft.NET.TestFramework/Utilities/DotnetVersionHelper.cs b/test/Microsoft.NET.TestFramework/Utilities/DotnetVersionHelper.cs new file mode 100644 index 000000000000..620f34eef929 --- /dev/null +++ b/test/Microsoft.NET.TestFramework/Utilities/DotnetVersionHelper.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text.RegularExpressions; + +namespace Microsoft.NET.TestFramework.Utilities +{ + public static class DotnetVersionHelper + { + public static string GetPreviousDotnetVersion() + { + string currentFramework = ToolsetInfo.CurrentTargetFramework; + var match = Regex.Match(currentFramework, @"^net(\d+)\.(\d+)$"); + if (!match.Success) + { + throw new InvalidOperationException($"Invalid target framework format: {currentFramework}"); + } + + int majorVersion = int.Parse(match.Groups[1].Value); + + if (majorVersion > 0) + { + majorVersion--; + } + else + { + throw new InvalidOperationException($"Cannot determine previous version for target framework: {currentFramework}"); + } + + return $"net{majorVersion}.0"; + } + } +} diff --git a/test/Microsoft.NET.TestFramework/Utilities/RegexPatternHelper.cs b/test/Microsoft.NET.TestFramework/Utilities/RegexPatternHelper.cs new file mode 100644 index 000000000000..b9bf26f694c5 --- /dev/null +++ b/test/Microsoft.NET.TestFramework/Utilities/RegexPatternHelper.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.DotNet.Tools.Common; + +namespace Microsoft.NET.TestFramework.Utilities +{ + public static class RegexPatternHelper + { + public static string GenerateProjectRegexPattern(string projectName, string result, bool useCurrentVersion, string? exitCode = null) + { + string version = useCurrentVersion ? ToolsetInfo.CurrentTargetFramework : DotnetVersionHelper.GetPreviousDotnetVersion(); + string exitCodePattern = exitCode == null ? string.Empty : $@".*\s+Exit code: {exitCode}"; + return $@".+{PathUtility.GetDirectorySeparatorChar()}{version}{PathUtility.GetDirectorySeparatorChar()}{projectName}\.dll\s+\({version}\|[a-zA-Z][1-9]+\)\s{result}{exitCodePattern}"; + } + + public static string GenerateProjectRegexPattern(string projectName, bool useCurrentVersion, string prefix, List? suffix = null) + { + string version = useCurrentVersion ? ToolsetInfo.CurrentTargetFramework : DotnetVersionHelper.GetPreviousDotnetVersion(); + string pattern = $@"{prefix}.*{PathUtility.GetDirectorySeparatorChar()}{projectName}\.dll\s+\({version}\|[a-zA-Z][1-9]+\)"; + + if (suffix == null) + { + return pattern; + } + + foreach (string s in suffix) + { + pattern += $@"\s+{s}"; + } + + return pattern; + } + } +} diff --git a/test/Msbuild.Tests.Utilities/Msbuild.Tests.Utilities.csproj b/test/Msbuild.Tests.Utilities/Msbuild.Tests.Utilities.csproj index 94c82028582a..8ec880dcddaf 100644 --- a/test/Msbuild.Tests.Utilities/Msbuild.Tests.Utilities.csproj +++ b/test/Msbuild.Tests.Utilities/Msbuild.Tests.Utilities.csproj @@ -9,7 +9,6 @@ - diff --git a/test/TestAssets/TestProjects/EmptyFolder/file.txt b/test/TestAssets/TestProjects/EmptyFolder/file.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/TestAssets/TestProjects/HybridTestRunnerTestProjects/AnotherTestProject/AnotherTestProject.csproj b/test/TestAssets/TestProjects/HybridTestRunnerTestProjects/AnotherTestProject/AnotherTestProject.csproj new file mode 100644 index 000000000000..37286601726d --- /dev/null +++ b/test/TestAssets/TestProjects/HybridTestRunnerTestProjects/AnotherTestProject/AnotherTestProject.csproj @@ -0,0 +1,20 @@ + + + + + $(CurrentTargetFramework) + latest + enable + enable + + + + + + + + + + + + \ No newline at end of file diff --git a/test/TestAssets/TestProjects/HybridTestRunnerTestProjects/AnotherTestProject/MSTestSettings.cs b/test/TestAssets/TestProjects/HybridTestRunnerTestProjects/AnotherTestProject/MSTestSettings.cs new file mode 100644 index 000000000000..aaf278c844f0 --- /dev/null +++ b/test/TestAssets/TestProjects/HybridTestRunnerTestProjects/AnotherTestProject/MSTestSettings.cs @@ -0,0 +1 @@ +[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)] diff --git a/test/TestAssets/TestProjects/HybridTestRunnerTestProjects/AnotherTestProject/Test1.cs b/test/TestAssets/TestProjects/HybridTestRunnerTestProjects/AnotherTestProject/Test1.cs new file mode 100644 index 000000000000..46eeff4520ba --- /dev/null +++ b/test/TestAssets/TestProjects/HybridTestRunnerTestProjects/AnotherTestProject/Test1.cs @@ -0,0 +1,11 @@ +namespace AnotherTestProject +{ + [TestClass] + public sealed class Test1 + { + [TestMethod] + public void TestMethod1() + { + } + } +} diff --git a/test/TestAssets/TestProjects/HybridTestRunnerTestProjects/HybridTestRunnerTestProjects.sln b/test/TestAssets/TestProjects/HybridTestRunnerTestProjects/HybridTestRunnerTestProjects.sln new file mode 100644 index 000000000000..027f72f15fbe --- /dev/null +++ b/test/TestAssets/TestProjects/HybridTestRunnerTestProjects/HybridTestRunnerTestProjects.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35415.258 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OtherTestProject", "OtherTestProject\OtherTestProject.csproj", "{8683AE78-764B-46C2-98D4-8A3031CBA27E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AnotherTestProject", "AnotherTestProject\AnotherTestProject.csproj", "{2604B2BA-D36A-461D-9BB3-207E4253051C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8683AE78-764B-46C2-98D4-8A3031CBA27E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8683AE78-764B-46C2-98D4-8A3031CBA27E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8683AE78-764B-46C2-98D4-8A3031CBA27E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8683AE78-764B-46C2-98D4-8A3031CBA27E}.Release|Any CPU.Build.0 = Release|Any CPU + {2604B2BA-D36A-461D-9BB3-207E4253051C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2604B2BA-D36A-461D-9BB3-207E4253051C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2604B2BA-D36A-461D-9BB3-207E4253051C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2604B2BA-D36A-461D-9BB3-207E4253051C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/test/TestAssets/TestProjects/HybridTestRunnerTestProjects/OtherTestProject/OtherTestProject.csproj b/test/TestAssets/TestProjects/HybridTestRunnerTestProjects/OtherTestProject/OtherTestProject.csproj new file mode 100644 index 000000000000..11c124c3ee7e --- /dev/null +++ b/test/TestAssets/TestProjects/HybridTestRunnerTestProjects/OtherTestProject/OtherTestProject.csproj @@ -0,0 +1,17 @@ + + + + + Exe + $(CurrentTargetFramework) + enable + enable + true + true + + + + + + + diff --git a/test/TestAssets/TestProjects/HybridTestRunnerTestProjects/OtherTestProject/Program.cs b/test/TestAssets/TestProjects/HybridTestRunnerTestProjects/OtherTestProject/Program.cs new file mode 100644 index 000000000000..f8fcbb648156 --- /dev/null +++ b/test/TestAssets/TestProjects/HybridTestRunnerTestProjects/OtherTestProject/Program.cs @@ -0,0 +1,106 @@ +//See https://aka.ms/new-console-template for more information + +//Opt -out telemetry + +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +//testApplicationBuilder.AddMSTest(() => new[] { Assembly.GetEntryAssembly()! }); +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => new[] { + typeof(TestNodeUpdateMessage), + typeof(SessionFileArtifact), + typeof(TestNodeFileArtifact), + typeof(FileArtifact), }; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test0", + DisplayName = "Test0", + Properties = new PropertyBag(new DiscoveredTestNodeStateProperty()), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test0", + DisplayName = "Test0", + Properties = new PropertyBag(new PassedTestNodeStateProperty("OK")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test1", + DisplayName = "Test1", + Properties = new PropertyBag(new SkippedTestNodeStateProperty("OK skipped!")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test2", + DisplayName = "Test2", + Properties = new PropertyBag(new FailedTestNodeStateProperty(new Exception("this is a failed test"), "not OK")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test3", + DisplayName = "Test3", + Properties = new PropertyBag(new TimeoutTestNodeStateProperty(new Exception("this is a timeout exception"), "not OK")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test4", + DisplayName = "Test4", + Properties = new PropertyBag(new ErrorTestNodeStateProperty(new Exception("this is an exception"), "not OK")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test5", + DisplayName = "Test5", + Properties = new PropertyBag(new CancelledTestNodeStateProperty(new Exception("this is a cancelled exception"), "not OK")), + })); + + await context.MessageBus.PublishAsync(this, new FileArtifact(new FileInfo("file.txt"), "file", "file description")); + + await context.MessageBus.PublishAsync(this, new SessionFileArtifact(context.Request.Session.SessionUid, new FileInfo("sessionFile.txt"), "sessionFile", "description")); + + await context.MessageBus.PublishAsync(this, new TestNodeFileArtifact(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test6 id", + DisplayName = "Test6", + Properties = new PropertyBag(new PassedTestNodeStateProperty("OK")), + }, new FileInfo("testNodeFile.txt"), "testNodeFile", "description")); + //await Task.CompletedTask; + context.Complete(); + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/KitchenSink/TestApp/TestApp.csproj b/test/TestAssets/TestProjects/KitchenSink/TestApp/TestApp.csproj index 69e33cb831b4..51887908e306 100644 --- a/test/TestAssets/TestProjects/KitchenSink/TestApp/TestApp.csproj +++ b/test/TestAssets/TestProjects/KitchenSink/TestApp/TestApp.csproj @@ -22,6 +22,7 @@ false <_WinFormsUITypeEditorSupport>true true + true true false true @@ -49,6 +50,7 @@ 2 9 true + true <_ActiveXImplSupport>true <_WinFormsBindingSupport>true <_WinFormsDesignTimeFeaturesSupport>true diff --git a/test/TestAssets/TestProjects/MSTestMetaPackageProjectWithMultipleTFMsSolution/MSTestMetaPackageProjectWithMultipleTFMsSolution.sln b/test/TestAssets/TestProjects/MSTestMetaPackageProjectWithMultipleTFMsSolution/MSTestMetaPackageProjectWithMultipleTFMsSolution.sln new file mode 100644 index 000000000000..27a9cf62907c --- /dev/null +++ b/test/TestAssets/TestProjects/MSTestMetaPackageProjectWithMultipleTFMsSolution/MSTestMetaPackageProjectWithMultipleTFMsSolution.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35415.258 main +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "TestProject\TestProject.csproj", "{0D246F24-651A-479B-AC3C-8D94F66A5E7E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0D246F24-651A-479B-AC3C-8D94F66A5E7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0D246F24-651A-479B-AC3C-8D94F66A5E7E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0D246F24-651A-479B-AC3C-8D94F66A5E7E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0D246F24-651A-479B-AC3C-8D94F66A5E7E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/test/TestAssets/TestProjects/MSTestMetaPackageProjectWithMultipleTFMsSolution/TestProject/TestProject.csproj b/test/TestAssets/TestProjects/MSTestMetaPackageProjectWithMultipleTFMsSolution/TestProject/TestProject.csproj new file mode 100644 index 000000000000..bd1a98705f81 --- /dev/null +++ b/test/TestAssets/TestProjects/MSTestMetaPackageProjectWithMultipleTFMsSolution/TestProject/TestProject.csproj @@ -0,0 +1,36 @@ + + + + + + true + + Exe + + $(CurrentTargetFramework) + enable + enable + + false + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/TestAssets/TestProjects/MSTestMetaPackageProjectWithMultipleTFMsSolution/TestProject/UnitTest1.cs b/test/TestAssets/TestProjects/MSTestMetaPackageProjectWithMultipleTFMsSolution/TestProject/UnitTest1.cs new file mode 100644 index 000000000000..cfba2da22107 --- /dev/null +++ b/test/TestAssets/TestProjects/MSTestMetaPackageProjectWithMultipleTFMsSolution/TestProject/UnitTest1.cs @@ -0,0 +1,25 @@ +namespace TestProject; + +[TestClass] +public class UnitTest1 +{ + [TestMethod] + public void TestMethod1() + { + Assert.AreEqual(1, 1); + } + +#if NET9_0 + [TestMethod] + public void TestMethod2() + { + Assert.AreEqual(1, 1); + } +#endif + + [TestMethod] + public void TestMethod3() + { + Assert.AreEqual(1, 0); + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/AnotherTestProject/AnotherTestProject.csproj b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/AnotherTestProject/AnotherTestProject.csproj new file mode 100644 index 000000000000..d2691f7d2109 --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/AnotherTestProject/AnotherTestProject.csproj @@ -0,0 +1,20 @@ + + + + + $(CurrentTargetFramework) + Exe + + enable + enable + true + + false + false + true + + + + + + diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/AnotherTestProject/Program.cs b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/AnotherTestProject/Program.cs new file mode 100644 index 000000000000..28a9001705af --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/AnotherTestProject/Program.cs @@ -0,0 +1,46 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => new[] { + typeof(TestNodeUpdateMessage) + }; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test0", + DisplayName = "Test0", + Properties = new PropertyBag(new PassedTestNodeStateProperty("OK")), + })); + + context.Complete(); + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/MultiTestProjectSolutionWithDifferentFailures.sln b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/MultiTestProjectSolutionWithDifferentFailures.sln new file mode 100644 index 000000000000..46fb718cc0c1 --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/MultiTestProjectSolutionWithDifferentFailures.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35415.258 main +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "TestProject\TestProject.csproj", "{EB61ABDF-A476-4CD0-8F05-78C1CFB8D011}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OtherTestProject", "OtherTestProject\OtherTestProject.csproj", "{10324BA1-E676-44C6-AF77-5186CEF704FC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AnotherTestProject", "AnotherTestProject\AnotherTestProject.csproj", "{7BCB85D3-DFED-4FAA-BCB5-5F0638331CC3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EB61ABDF-A476-4CD0-8F05-78C1CFB8D011}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EB61ABDF-A476-4CD0-8F05-78C1CFB8D011}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EB61ABDF-A476-4CD0-8F05-78C1CFB8D011}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EB61ABDF-A476-4CD0-8F05-78C1CFB8D011}.Release|Any CPU.Build.0 = Release|Any CPU + {10324BA1-E676-44C6-AF77-5186CEF704FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {10324BA1-E676-44C6-AF77-5186CEF704FC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {10324BA1-E676-44C6-AF77-5186CEF704FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {10324BA1-E676-44C6-AF77-5186CEF704FC}.Release|Any CPU.Build.0 = Release|Any CPU + {7BCB85D3-DFED-4FAA-BCB5-5F0638331CC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7BCB85D3-DFED-4FAA-BCB5-5F0638331CC3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7BCB85D3-DFED-4FAA-BCB5-5F0638331CC3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7BCB85D3-DFED-4FAA-BCB5-5F0638331CC3}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/OtherTestProject/OtherTestProject.csproj b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/OtherTestProject/OtherTestProject.csproj new file mode 100644 index 000000000000..d2691f7d2109 --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/OtherTestProject/OtherTestProject.csproj @@ -0,0 +1,20 @@ + + + + + $(CurrentTargetFramework) + Exe + + enable + enable + true + + false + false + true + + + + + + diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/OtherTestProject/Program.cs b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/OtherTestProject/Program.cs new file mode 100644 index 000000000000..bba220658aa8 --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/OtherTestProject/Program.cs @@ -0,0 +1,60 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => new[] { + typeof(TestNodeUpdateMessage) + }; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test1", + DisplayName = "Test1", + Properties = new PropertyBag(new PassedTestNodeStateProperty("OK")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test2", + DisplayName = "Test2", + Properties = new PropertyBag(new SkippedTestNodeStateProperty("OK skipped!")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test3", + DisplayName = "Test3", + Properties = new PropertyBag(new FailedTestNodeStateProperty(new Exception("this is a failed test"), "not OK")), + })); + + context.Complete(); + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/TestProject/Program.cs b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/TestProject/Program.cs new file mode 100644 index 000000000000..b8efb9c72be9 --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/TestProject/Program.cs @@ -0,0 +1,38 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => []; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + context.Complete(); + await Task.CompletedTask; + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/TestProject/TestProject.csproj b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/TestProject/TestProject.csproj new file mode 100644 index 000000000000..d2691f7d2109 --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDifferentFailures/TestProject/TestProject.csproj @@ -0,0 +1,20 @@ + + + + + $(CurrentTargetFramework) + Exe + + enable + enable + true + + false + false + true + + + + + + diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDiscoveredTests/MultiTestProjectSolutionWithDiscoveredTests.sln b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDiscoveredTests/MultiTestProjectSolutionWithDiscoveredTests.sln new file mode 100644 index 000000000000..17275f0f8f30 --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDiscoveredTests/MultiTestProjectSolutionWithDiscoveredTests.sln @@ -0,0 +1,32 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35322.30 main +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "TestProject\TestProject.csproj", "{C43FCD94-028D-4DE8-96EC-A3663AE225B4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OtherTestProject", "OtherTestProject\OtherTestProject.csproj", "{6171FC1F-E2F2-4F66-A8DE-EC4765081661}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C43FCD94-028D-4DE8-96EC-A3663AE225B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C43FCD94-028D-4DE8-96EC-A3663AE225B4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C43FCD94-028D-4DE8-96EC-A3663AE225B4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C43FCD94-028D-4DE8-96EC-A3663AE225B4}.Release|Any CPU.Build.0 = Release|Any CPU + {C43FCD94-028D-4DE8-96EC-A3663AE225B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C43FCD94-028D-4DE8-96EC-A3663AE225B4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C43FCD94-028D-4DE8-96EC-A3663AE225B4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C43FCD94-028D-4DE8-96EC-A3663AE225B4}.Release|Any CPU.Build.0 = Release|Any CPU + {6171FC1F-E2F2-4F66-A8DE-EC4765081661}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6171FC1F-E2F2-4F66-A8DE-EC4765081661}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6171FC1F-E2F2-4F66-A8DE-EC4765081661}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6171FC1F-E2F2-4F66-A8DE-EC4765081661}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDiscoveredTests/OtherTestProject/OtherTestProject.csproj b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDiscoveredTests/OtherTestProject/OtherTestProject.csproj new file mode 100644 index 000000000000..0c30c0b8b8cd --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDiscoveredTests/OtherTestProject/OtherTestProject.csproj @@ -0,0 +1,20 @@ + + + + + $(CurrentTargetFramework) + Exe + + enable + enable + true + + false + false + true + + + + + + diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDiscoveredTests/OtherTestProject/Program.cs b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDiscoveredTests/OtherTestProject/Program.cs new file mode 100644 index 000000000000..ea33026cd253 --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDiscoveredTests/OtherTestProject/Program.cs @@ -0,0 +1,46 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => new[] { + typeof(TestNodeUpdateMessage) + }; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test1", + DisplayName = "Test1", + Properties = new PropertyBag(new DiscoveredTestNodeStateProperty()), + })); + + context.Complete(); + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDiscoveredTests/TestProject/Program.cs b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDiscoveredTests/TestProject/Program.cs new file mode 100644 index 000000000000..d6f6d84b2367 --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDiscoveredTests/TestProject/Program.cs @@ -0,0 +1,53 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => new[] { + typeof(TestNodeUpdateMessage) + }; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test0", + DisplayName = "Test0", + Properties = new PropertyBag(new DiscoveredTestNodeStateProperty()), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test2", + DisplayName = "Test2", + Properties = new PropertyBag(new DiscoveredTestNodeStateProperty()), + })); + + context.Complete(); + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDiscoveredTests/TestProject/TestProject.csproj b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDiscoveredTests/TestProject/TestProject.csproj new file mode 100644 index 000000000000..0c30c0b8b8cd --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithDiscoveredTests/TestProject/TestProject.csproj @@ -0,0 +1,20 @@ + + + + + $(CurrentTargetFramework) + Exe + + enable + enable + true + + false + false + true + + + + + + diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/MultiTestProjectSolutionWithTests.sln b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/MultiTestProjectSolutionWithTests.sln new file mode 100644 index 000000000000..a102989a3557 --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/MultiTestProjectSolutionWithTests.sln @@ -0,0 +1,32 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35322.30 main +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "TestProject/TestProject.csproj", "{C43FCD94-028D-4DE8-96EC-A3663AE225B4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OtherTestProject", "OtherTestProject/OtherTestProject.csproj", "{6171FC1F-E2F2-4F66-A8DE-EC4765081661}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C43FCD94-028D-4DE8-96EC-A3663AE225B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C43FCD94-028D-4DE8-96EC-A3663AE225B4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C43FCD94-028D-4DE8-96EC-A3663AE225B4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C43FCD94-028D-4DE8-96EC-A3663AE225B4}.Release|Any CPU.Build.0 = Release|Any CPU + {C43FCD94-028D-4DE8-96EC-A3663AE225B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C43FCD94-028D-4DE8-96EC-A3663AE225B4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C43FCD94-028D-4DE8-96EC-A3663AE225B4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C43FCD94-028D-4DE8-96EC-A3663AE225B4}.Release|Any CPU.Build.0 = Release|Any CPU + {6171FC1F-E2F2-4F66-A8DE-EC4765081661}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6171FC1F-E2F2-4F66-A8DE-EC4765081661}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6171FC1F-E2F2-4F66-A8DE-EC4765081661}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6171FC1F-E2F2-4F66-A8DE-EC4765081661}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/OtherTestProject/OtherTestProject.csproj b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/OtherTestProject/OtherTestProject.csproj new file mode 100644 index 000000000000..0c30c0b8b8cd --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/OtherTestProject/OtherTestProject.csproj @@ -0,0 +1,20 @@ + + + + + $(CurrentTargetFramework) + Exe + + enable + enable + true + + false + false + true + + + + + + diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/OtherTestProject/Program.cs b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/OtherTestProject/Program.cs new file mode 100644 index 000000000000..7f1ee5386c15 --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/OtherTestProject/Program.cs @@ -0,0 +1,53 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => new[] { + typeof(TestNodeUpdateMessage) + }; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test1", + DisplayName = "Test1", + Properties = new PropertyBag(new PassedTestNodeStateProperty("OK")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test2", + DisplayName = "Test2", + Properties = new PropertyBag(new SkippedTestNodeStateProperty("skipped")), + })); + + context.Complete(); + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/SolutionFilter/OtherTestProjects.slnf b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/SolutionFilter/OtherTestProjects.slnf new file mode 100644 index 000000000000..32d256648c60 --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/SolutionFilter/OtherTestProjects.slnf @@ -0,0 +1,8 @@ +{ + "solution": { + "path": "../MultiTestProjectSolutionWithTests.sln", + "projects": [ + "TestProject/TestProject.csproj" + ] + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/TestProject/Program.cs b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/TestProject/Program.cs new file mode 100644 index 000000000000..cdecea10ffeb --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/TestProject/Program.cs @@ -0,0 +1,60 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => new[] { + typeof(TestNodeUpdateMessage) + }; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test0", + DisplayName = "Test0", + Properties = new PropertyBag(new PassedTestNodeStateProperty("OK")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test1", + DisplayName = "Test1", + Properties = new PropertyBag(new SkippedTestNodeStateProperty("OK skipped!")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test2", + DisplayName = "Test2", + Properties = new PropertyBag(new FailedTestNodeStateProperty(new Exception("this is a failed test"), "not OK")), + })); + + context.Complete(); + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/TestProject/TestProject.csproj b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/TestProject/TestProject.csproj new file mode 100644 index 000000000000..0c30c0b8b8cd --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/TestProject/TestProject.csproj @@ -0,0 +1,20 @@ + + + + + $(CurrentTargetFramework) + Exe + + enable + enable + true + + false + false + true + + + + + + diff --git a/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/TestProjects.slnf b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/TestProjects.slnf new file mode 100644 index 000000000000..aecf39dc8acc --- /dev/null +++ b/test/TestAssets/TestProjects/MultiTestProjectSolutionWithTests/TestProjects.slnf @@ -0,0 +1,8 @@ +{ + "solution": { + "path": "MultiTestProjectSolutionWithTests.sln", + "projects": [ + "TestProject/TestProject.csproj" + ] + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/MultipleTestProjectSolution/AnotherTestProject/AnotherTestProject.csproj b/test/TestAssets/TestProjects/MultipleTestProjectSolution/AnotherTestProject/AnotherTestProject.csproj new file mode 100644 index 000000000000..0c30c0b8b8cd --- /dev/null +++ b/test/TestAssets/TestProjects/MultipleTestProjectSolution/AnotherTestProject/AnotherTestProject.csproj @@ -0,0 +1,20 @@ + + + + + $(CurrentTargetFramework) + Exe + + enable + enable + true + + false + false + true + + + + + + diff --git a/test/TestAssets/TestProjects/MultipleTestProjectSolution/AnotherTestProject/Program.cs b/test/TestAssets/TestProjects/MultipleTestProjectSolution/AnotherTestProject/Program.cs new file mode 100644 index 000000000000..b8efb9c72be9 --- /dev/null +++ b/test/TestAssets/TestProjects/MultipleTestProjectSolution/AnotherTestProject/Program.cs @@ -0,0 +1,38 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => []; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + context.Complete(); + await Task.CompletedTask; + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/MultipleTestProjectSolution/MultipleTestProjectSolution.sln b/test/TestAssets/TestProjects/MultipleTestProjectSolution/MultipleTestProjectSolution.sln new file mode 100644 index 000000000000..e9eba761916e --- /dev/null +++ b/test/TestAssets/TestProjects/MultipleTestProjectSolution/MultipleTestProjectSolution.sln @@ -0,0 +1,33 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35322.30 main +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "TestProject\TestProject.csproj", "{C6D846BA-EFD0-44A5-A07C-6C50D264F63E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OtherTestProject", "OtherTestProject\OtherTestProject.csproj", "{0E527CEF-292C-4265-81EB-4C9F51072219}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AnotherTestProject", "AnotherTestProject\AnotherTestProject.csproj", "{9C734AA0-998F-4CB8-BEB8-043D47AB9996}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C6D846BA-EFD0-44A5-A07C-6C50D264F63E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C6D846BA-EFD0-44A5-A07C-6C50D264F63E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C6D846BA-EFD0-44A5-A07C-6C50D264F63E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C6D846BA-EFD0-44A5-A07C-6C50D264F63E}.Release|Any CPU.Build.0 = Release|Any CPU + {0E527CEF-292C-4265-81EB-4C9F51072219}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0E527CEF-292C-4265-81EB-4C9F51072219}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0E527CEF-292C-4265-81EB-4C9F51072219}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0E527CEF-292C-4265-81EB-4C9F51072219}.Release|Any CPU.Build.0 = Release|Any CPU + {9C734AA0-998F-4CB8-BEB8-043D47AB9996}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9C734AA0-998F-4CB8-BEB8-043D47AB9996}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9C734AA0-998F-4CB8-BEB8-043D47AB9996}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9C734AA0-998F-4CB8-BEB8-043D47AB9996}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/test/TestAssets/TestProjects/MultipleTestProjectSolution/OtherTestProject/OtherTestProject.csproj b/test/TestAssets/TestProjects/MultipleTestProjectSolution/OtherTestProject/OtherTestProject.csproj new file mode 100644 index 000000000000..ef46af6c6117 --- /dev/null +++ b/test/TestAssets/TestProjects/MultipleTestProjectSolution/OtherTestProject/OtherTestProject.csproj @@ -0,0 +1,20 @@ + + + + + $(CurrentTargetFramework) + Exe + + enable + enable + true + + false + false + true + + + + + + diff --git a/test/TestAssets/TestProjects/MultipleTestProjectSolution/OtherTestProject/Program.cs b/test/TestAssets/TestProjects/MultipleTestProjectSolution/OtherTestProject/Program.cs new file mode 100644 index 000000000000..b8efb9c72be9 --- /dev/null +++ b/test/TestAssets/TestProjects/MultipleTestProjectSolution/OtherTestProject/Program.cs @@ -0,0 +1,38 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => []; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + context.Complete(); + await Task.CompletedTask; + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/MultipleTestProjectSolution/TestProject/Program.cs b/test/TestAssets/TestProjects/MultipleTestProjectSolution/TestProject/Program.cs new file mode 100644 index 000000000000..b8efb9c72be9 --- /dev/null +++ b/test/TestAssets/TestProjects/MultipleTestProjectSolution/TestProject/Program.cs @@ -0,0 +1,38 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => []; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + context.Complete(); + await Task.CompletedTask; + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/MultipleTestProjectSolution/TestProject/TestProject.csproj b/test/TestAssets/TestProjects/MultipleTestProjectSolution/TestProject/TestProject.csproj new file mode 100644 index 000000000000..7e7bccb38287 --- /dev/null +++ b/test/TestAssets/TestProjects/MultipleTestProjectSolution/TestProject/TestProject.csproj @@ -0,0 +1,20 @@ + + + + + $(CurrentTargetFramework) + Exe + + enable + enable + true + + false + false + true + + + + + + diff --git a/test/TestAssets/TestProjects/MultipleTestProjectsWithoutSolution/AnotherTestProject/AnotherTestProject.csproj b/test/TestAssets/TestProjects/MultipleTestProjectsWithoutSolution/AnotherTestProject/AnotherTestProject.csproj new file mode 100644 index 000000000000..19a9d61c98f1 --- /dev/null +++ b/test/TestAssets/TestProjects/MultipleTestProjectsWithoutSolution/AnotherTestProject/AnotherTestProject.csproj @@ -0,0 +1,20 @@ + + + + + net8.0 + Exe + + enable + enable + true + + false + false + true + + + + + + diff --git a/test/TestAssets/TestProjects/MultipleTestProjectsWithoutSolution/AnotherTestProject/Program.cs b/test/TestAssets/TestProjects/MultipleTestProjectsWithoutSolution/AnotherTestProject/Program.cs new file mode 100644 index 000000000000..b8efb9c72be9 --- /dev/null +++ b/test/TestAssets/TestProjects/MultipleTestProjectsWithoutSolution/AnotherTestProject/Program.cs @@ -0,0 +1,38 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => []; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + context.Complete(); + await Task.CompletedTask; + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/MultipleTestProjectsWithoutSolution/OtherTestProject/OtherTestProject.csproj b/test/TestAssets/TestProjects/MultipleTestProjectsWithoutSolution/OtherTestProject/OtherTestProject.csproj new file mode 100644 index 000000000000..1acd030edec2 --- /dev/null +++ b/test/TestAssets/TestProjects/MultipleTestProjectsWithoutSolution/OtherTestProject/OtherTestProject.csproj @@ -0,0 +1,20 @@ + + + + + net8.0 + Exe + + enable + enable + true + + false + false + true + + + + + + diff --git a/test/TestAssets/TestProjects/MultipleTestProjectsWithoutSolution/OtherTestProject/Program.cs b/test/TestAssets/TestProjects/MultipleTestProjectsWithoutSolution/OtherTestProject/Program.cs new file mode 100644 index 000000000000..b8efb9c72be9 --- /dev/null +++ b/test/TestAssets/TestProjects/MultipleTestProjectsWithoutSolution/OtherTestProject/Program.cs @@ -0,0 +1,38 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => []; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + context.Complete(); + await Task.CompletedTask; + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/MultipleTestProjectsWithoutSolution/TestProject/Program.cs b/test/TestAssets/TestProjects/MultipleTestProjectsWithoutSolution/TestProject/Program.cs new file mode 100644 index 000000000000..b8efb9c72be9 --- /dev/null +++ b/test/TestAssets/TestProjects/MultipleTestProjectsWithoutSolution/TestProject/Program.cs @@ -0,0 +1,38 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => []; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + context.Complete(); + await Task.CompletedTask; + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/MultipleTestProjectsWithoutSolution/TestProject/TestProject.csproj b/test/TestAssets/TestProjects/MultipleTestProjectsWithoutSolution/TestProject/TestProject.csproj new file mode 100644 index 000000000000..35acc103cb62 --- /dev/null +++ b/test/TestAssets/TestProjects/MultipleTestProjectsWithoutSolution/TestProject/TestProject.csproj @@ -0,0 +1,20 @@ + + + + + net8.0 + Exe + + enable + enable + true + + false + false + true + + + + + + diff --git a/test/TestAssets/TestProjects/ProjectSolutionForMultipleTFMs/OtherTestProject/OtherTestProject.csproj b/test/TestAssets/TestProjects/ProjectSolutionForMultipleTFMs/OtherTestProject/OtherTestProject.csproj new file mode 100644 index 000000000000..0c30c0b8b8cd --- /dev/null +++ b/test/TestAssets/TestProjects/ProjectSolutionForMultipleTFMs/OtherTestProject/OtherTestProject.csproj @@ -0,0 +1,20 @@ + + + + + $(CurrentTargetFramework) + Exe + + enable + enable + true + + false + false + true + + + + + + diff --git a/test/TestAssets/TestProjects/ProjectSolutionForMultipleTFMs/OtherTestProject/Program.cs b/test/TestAssets/TestProjects/ProjectSolutionForMultipleTFMs/OtherTestProject/Program.cs new file mode 100644 index 000000000000..dd865efbf0b1 --- /dev/null +++ b/test/TestAssets/TestProjects/ProjectSolutionForMultipleTFMs/OtherTestProject/Program.cs @@ -0,0 +1,53 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => new[] { + typeof(TestNodeUpdateMessage) + }; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test1", + DisplayName = "Test1", + Properties = new PropertyBag(new PassedTestNodeStateProperty("OK")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test2", + DisplayName = "Test2", + Properties = new PropertyBag(new SkippedTestNodeStateProperty("OK skipped!")), + })); + + context.Complete(); + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/ProjectSolutionForMultipleTFMs/ProjectSolutionForMultipleTFMs.sln b/test/TestAssets/TestProjects/ProjectSolutionForMultipleTFMs/ProjectSolutionForMultipleTFMs.sln new file mode 100644 index 000000000000..7cef80cb7ceb --- /dev/null +++ b/test/TestAssets/TestProjects/ProjectSolutionForMultipleTFMs/ProjectSolutionForMultipleTFMs.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35322.30 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OtherTestProject", "OtherTestProject\OtherTestProject.csproj", "{EF95A0BF-ADC3-4B37-B1EB-0436D24D615F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "TestProject\TestProject.csproj", "{4B9F47C4-06A0-4A41-9F8D-CEC199C49CAA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EF95A0BF-ADC3-4B37-B1EB-0436D24D615F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF95A0BF-ADC3-4B37-B1EB-0436D24D615F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF95A0BF-ADC3-4B37-B1EB-0436D24D615F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF95A0BF-ADC3-4B37-B1EB-0436D24D615F}.Release|Any CPU.Build.0 = Release|Any CPU + {4B9F47C4-06A0-4A41-9F8D-CEC199C49CAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4B9F47C4-06A0-4A41-9F8D-CEC199C49CAA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4B9F47C4-06A0-4A41-9F8D-CEC199C49CAA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4B9F47C4-06A0-4A41-9F8D-CEC199C49CAA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/test/TestAssets/TestProjects/ProjectSolutionForMultipleTFMs/TestProject/Program.cs b/test/TestAssets/TestProjects/ProjectSolutionForMultipleTFMs/TestProject/Program.cs new file mode 100644 index 000000000000..d32c5029df4e --- /dev/null +++ b/test/TestAssets/TestProjects/ProjectSolutionForMultipleTFMs/TestProject/Program.cs @@ -0,0 +1,62 @@ +using Microsoft.Testing.Extensions; +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); +testApplicationBuilder.AddTrxReportProvider(); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => new[] { + typeof(TestNodeUpdateMessage) + }; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test1", + DisplayName = "Test1", + Properties = new PropertyBag(new PassedTestNodeStateProperty("OK")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test2", + DisplayName = "Test2", + Properties = new PropertyBag(new SkippedTestNodeStateProperty("OK skipped!")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test3", + DisplayName = "Test3", + Properties = new PropertyBag(new FailedTestNodeStateProperty(new Exception("this is a failed test"), "not OK")), + })); + + context.Complete(); + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/ProjectSolutionForMultipleTFMs/TestProject/TestProject.csproj b/test/TestAssets/TestProjects/ProjectSolutionForMultipleTFMs/TestProject/TestProject.csproj new file mode 100644 index 000000000000..ffc8d3b25f14 --- /dev/null +++ b/test/TestAssets/TestProjects/ProjectSolutionForMultipleTFMs/TestProject/TestProject.csproj @@ -0,0 +1,21 @@ + + + + + $(CurrentTargetFramework) + Exe + + enable + enable + true + + false + false + true + + + + + + + diff --git a/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingLibProjToEmptySln.slnx b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingLibProjToEmptySln.slnx index e3caa7e0055a..32170164c710 100644 --- a/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingLibProjToEmptySln.slnx +++ b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingLibProjToEmptySln.slnx @@ -1,8 +1,3 @@ - - - - - diff --git a/test/TestAssets/TestProjects/TestAppWithLaunchSettings/Program.cs b/test/TestAssets/TestProjects/TestAppWithLaunchSettings/Program.cs index 644ce5b625be..d4e4e9f13458 100644 --- a/test/TestAssets/TestProjects/TestAppWithLaunchSettings/Program.cs +++ b/test/TestAssets/TestProjects/TestAppWithLaunchSettings/Program.cs @@ -10,8 +10,10 @@ public class Program public static void Main(string[] args) { Console.WriteLine("Hello world"); - Console.WriteLine($"MyCoolEnvironmentVariableKey={Environment.GetEnvironmentVariable("MyCoolEnvironmentVariableKey")}"); - Console.WriteLine($"DOTNET_LAUNCH_PROFILE={Environment.GetEnvironmentVariable("DOTNET_LAUNCH_PROFILE")}"); + Console.WriteLine($"env: MyCoolEnvironmentVariableKey={Environment.GetEnvironmentVariable("MyCoolEnvironmentVariableKey")}"); + Console.WriteLine($"env: DOTNET_LAUNCH_PROFILE={Environment.GetEnvironmentVariable("DOTNET_LAUNCH_PROFILE")}"); + Console.WriteLine($"env: ASPNETCORE_URLS={Environment.GetEnvironmentVariable("ASPNETCORE_URLS")}"); + Console.WriteLine($"env: Configuration={Environment.GetEnvironmentVariable("Configuration")}"); if (args.Length > 0) { Console.WriteLine(args[0]); diff --git a/test/TestAssets/TestProjects/TestAppWithLaunchSettings/Properties/launchSettings.json b/test/TestAssets/TestProjects/TestAppWithLaunchSettings/Properties/launchSettings.json index 5ac0ee3cff41..3b6883ccd6c6 100644 --- a/test/TestAssets/TestProjects/TestAppWithLaunchSettings/Properties/launchSettings.json +++ b/test/TestAssets/TestProjects/TestAppWithLaunchSettings/Properties/launchSettings.json @@ -3,10 +3,20 @@ "TestAppWithLaunchSettings": { "commandName": "Project", "dotnetRunMessages": "true", + "applicationUrl": "http://localhost:5000", "commandLineArgs": "TestAppCommandLineArguments SecondTestAppCommandLineArguments", "environmentVariables": { "MyCoolEnvironmentVariableKey": "MyCoolEnvironmentVariableValue" } + }, + "Profile2": { + "commandName": "Project", + "dotnetRunMessages": "true", + "applicationUrl": "http://localhost:5000", + "environmentVariables": { + "DOTNET_LAUNCH_PROFILE": "XYZ", + "ASPNETCORE_URLS": "XYZ" + } } } } \ No newline at end of file diff --git a/test/TestAssets/TestProjects/TestAppWithSlnxAndSolutionFilters/App.slnf b/test/TestAssets/TestProjects/TestAppWithSlnxAndSolutionFilters/App.slnf new file mode 100644 index 000000000000..cb9bb9900dca --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithSlnxAndSolutionFilters/App.slnf @@ -0,0 +1,8 @@ +{ + "solution": { + "path": "./App.slnx", + "projects": [ + "src\\App\\App.csproj" + ] + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/TestAppWithSlnxAndSolutionFilters/App.slnx b/test/TestAssets/TestProjects/TestAppWithSlnxAndSolutionFilters/App.slnx new file mode 100644 index 000000000000..0869737e4e89 --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithSlnxAndSolutionFilters/App.slnx @@ -0,0 +1,4 @@ + + + + diff --git a/test/TestAssets/TestProjects/TestProjectFileAndSolutionFile/MultipleTestProjectSolution.sln b/test/TestAssets/TestProjects/TestProjectFileAndSolutionFile/MultipleTestProjectSolution.sln new file mode 100644 index 000000000000..4be44315b612 --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectFileAndSolutionFile/MultipleTestProjectSolution.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35322.30 main +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "TestProject.csproj", "{C6D846BA-EFD0-44A5-A07C-6C50D264F63E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C6D846BA-EFD0-44A5-A07C-6C50D264F63E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C6D846BA-EFD0-44A5-A07C-6C50D264F63E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C6D846BA-EFD0-44A5-A07C-6C50D264F63E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C6D846BA-EFD0-44A5-A07C-6C50D264F63E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/test/TestAssets/TestProjects/TestProjectFileAndSolutionFile/Program.cs b/test/TestAssets/TestProjects/TestProjectFileAndSolutionFile/Program.cs new file mode 100644 index 000000000000..b8efb9c72be9 --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectFileAndSolutionFile/Program.cs @@ -0,0 +1,38 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => []; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + context.Complete(); + await Task.CompletedTask; + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/TestProjectFileAndSolutionFile/TestProject.csproj b/test/TestAssets/TestProjects/TestProjectFileAndSolutionFile/TestProject.csproj new file mode 100644 index 000000000000..7e7bccb38287 --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectFileAndSolutionFile/TestProject.csproj @@ -0,0 +1,20 @@ + + + + + $(CurrentTargetFramework) + Exe + + enable + enable + true + + false + false + true + + + + + + diff --git a/test/TestAssets/TestProjects/TestProjectSolution/TestProject/Program.cs b/test/TestAssets/TestProjects/TestProjectSolution/TestProject/Program.cs new file mode 100644 index 000000000000..b8efb9c72be9 --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectSolution/TestProject/Program.cs @@ -0,0 +1,38 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => []; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + context.Complete(); + await Task.CompletedTask; + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/TestProjectSolution/TestProject/TestProject.csproj b/test/TestAssets/TestProjects/TestProjectSolution/TestProject/TestProject.csproj new file mode 100644 index 000000000000..0c30c0b8b8cd --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectSolution/TestProject/TestProject.csproj @@ -0,0 +1,20 @@ + + + + + $(CurrentTargetFramework) + Exe + + enable + enable + true + + false + false + true + + + + + + diff --git a/test/TestAssets/TestProjects/TestProjectSolution/TestProjectSolution.sln b/test/TestAssets/TestProjects/TestProjectSolution/TestProjectSolution.sln new file mode 100644 index 000000000000..15ee9bf00d5d --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectSolution/TestProjectSolution.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35322.30 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "TestProject\TestProject.csproj", "{A3CB990F-B603-4911-A669-87C60B41DF10}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A3CB990F-B603-4911-A669-87C60B41DF10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A3CB990F-B603-4911-A669-87C60B41DF10}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A3CB990F-B603-4911-A669-87C60B41DF10}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A3CB990F-B603-4911-A669-87C60B41DF10}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/test/TestAssets/TestProjects/TestProjectSolutionWithCodeCoverage/TestProject/Program.cs b/test/TestAssets/TestProjects/TestProjectSolutionWithCodeCoverage/TestProject/Program.cs new file mode 100644 index 000000000000..07fc4f4a8c25 --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectSolutionWithCodeCoverage/TestProject/Program.cs @@ -0,0 +1,15 @@ +namespace TestProject +{ + internal class Program + { + public static async global::System.Threading.Tasks.Task Main(string[] args) + { + Microsoft.Testing.Platform.Builder.ITestApplicationBuilder builder = await global::Microsoft.Testing.Platform.Builder.TestApplication.CreateBuilderAsync(args); + builder.AddSelfRegisteredExtensions(args); + using (global::Microsoft.Testing.Platform.Builder.ITestApplication app = await builder.BuildAsync()) + { + return await app.RunAsync(); + } + } + } +} diff --git a/test/TestAssets/TestProjects/TestProjectSolutionWithCodeCoverage/TestProject/Test1.cs b/test/TestAssets/TestProjects/TestProjectSolutionWithCodeCoverage/TestProject/Test1.cs new file mode 100644 index 000000000000..8bbbb841f05f --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectSolutionWithCodeCoverage/TestProject/Test1.cs @@ -0,0 +1,20 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace TestProject +{ + [TestClass] + public sealed class Test1 + { + [TestMethod] + public void TestMethod1() + { + Assert.AreEqual(1, 1); + } + + [TestMethod] + public void TestMethod2() + { + Assert.AreEqual(1, 2); + } + } +} diff --git a/test/TestAssets/TestProjects/TestProjectSolutionWithCodeCoverage/TestProject/TestProject.csproj b/test/TestAssets/TestProjects/TestProjectSolutionWithCodeCoverage/TestProject/TestProject.csproj new file mode 100644 index 000000000000..26d19ec54b4f --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectSolutionWithCodeCoverage/TestProject/TestProject.csproj @@ -0,0 +1,13 @@ + + + + + $(CurrentTargetFramework) + False + 17.12.6 + + + + + + \ No newline at end of file diff --git a/test/TestAssets/TestProjects/TestProjectSolutionWithCodeCoverage/TestProjectSolutionWithCodeCoverage.sln b/test/TestAssets/TestProjects/TestProjectSolutionWithCodeCoverage/TestProjectSolutionWithCodeCoverage.sln new file mode 100644 index 000000000000..13471530b1e4 --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectSolutionWithCodeCoverage/TestProjectSolutionWithCodeCoverage.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35415.258 main +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "TestProject\TestProject.csproj", "{44DB7F03-7556-4EBA-BF32-C538B3A05742}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {44DB7F03-7556-4EBA-BF32-C538B3A05742}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {44DB7F03-7556-4EBA-BF32-C538B3A05742}.Debug|Any CPU.Build.0 = Debug|Any CPU + {44DB7F03-7556-4EBA-BF32-C538B3A05742}.Release|Any CPU.ActiveCfg = Release|Any CPU + {44DB7F03-7556-4EBA-BF32-C538B3A05742}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/test/TestAssets/TestProjects/TestProjectSolutionWithTestsAndArtifacts/TestProject/Program.cs b/test/TestAssets/TestProjects/TestProjectSolutionWithTestsAndArtifacts/TestProject/Program.cs new file mode 100644 index 000000000000..db1b1ca08669 --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectSolutionWithTestsAndArtifacts/TestProject/Program.cs @@ -0,0 +1,103 @@ +//See https://aka.ms/new-console-template for more information + +//Opt -out telemetry + +using Microsoft.Testing.Extensions; +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +Environment.SetEnvironmentVariable("DOTNET_CLI_TELEMETRY_OPTOUT", "1"); + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +// Enable Trx +testApplicationBuilder.AddTrxReportProvider(); +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => new[] { + typeof(TestNodeUpdateMessage), + typeof(SessionFileArtifact), + typeof(TestNodeFileArtifact), + typeof(FileArtifact), }; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test1", + DisplayName = "Test1", + Properties = new PropertyBag(new PassedTestNodeStateProperty("OK")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test1", + DisplayName = "Test1", + Properties = new PropertyBag(new SkippedTestNodeStateProperty("OK skipped!")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test2", + DisplayName = "Test2", + Properties = new PropertyBag(new FailedTestNodeStateProperty(new Exception("this is a failed test"), "not OK")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test3", + DisplayName = "Test3", + Properties = new PropertyBag(new TimeoutTestNodeStateProperty(new Exception("this is a timeout exception"), "not OK")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Tes43", + DisplayName = "Test4", + Properties = new PropertyBag(new ErrorTestNodeStateProperty(new Exception("this is an exception"), "not OK")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test5", + DisplayName = "Test5", + Properties = new PropertyBag(new CancelledTestNodeStateProperty(new Exception("this is a cancelled exception"), "not OK")), + })); + + await context.MessageBus.PublishAsync(this, new FileArtifact(new FileInfo("file.txt"), "file", "file description")); + + await context.MessageBus.PublishAsync(this, new SessionFileArtifact(context.Request.Session.SessionUid, new FileInfo("sessionFile.txt"), "sessionFile", "description")); + + await context.MessageBus.PublishAsync(this, new TestNodeFileArtifact(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test6 id", + DisplayName = "Test6", + Properties = new PropertyBag(new PassedTestNodeStateProperty("OK")), + }, new FileInfo("testNodeFile.txt"), "testNodeFile", "description")); + + context.Complete(); + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/TestProjectSolutionWithTestsAndArtifacts/TestProject/TestProject.csproj b/test/TestAssets/TestProjects/TestProjectSolutionWithTestsAndArtifacts/TestProject/TestProject.csproj new file mode 100644 index 000000000000..ffc8d3b25f14 --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectSolutionWithTestsAndArtifacts/TestProject/TestProject.csproj @@ -0,0 +1,21 @@ + + + + + $(CurrentTargetFramework) + Exe + + enable + enable + true + + false + false + true + + + + + + + diff --git a/test/TestAssets/TestProjects/TestProjectSolutionWithTestsAndArtifacts/TestProjectSolutionWithTestsAndArtifacts.sln b/test/TestAssets/TestProjects/TestProjectSolutionWithTestsAndArtifacts/TestProjectSolutionWithTestsAndArtifacts.sln new file mode 100644 index 000000000000..f14170863d5a --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectSolutionWithTestsAndArtifacts/TestProjectSolutionWithTestsAndArtifacts.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35415.258 main +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "TestProject\TestProject.csproj", "{7DF6A00E-4EBA-4845-95FF-9C567E6687F6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7DF6A00E-4EBA-4845-95FF-9C567E6687F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7DF6A00E-4EBA-4845-95FF-9C567E6687F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7DF6A00E-4EBA-4845-95FF-9C567E6687F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7DF6A00E-4EBA-4845-95FF-9C567E6687F6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/test/TestAssets/TestProjects/TestProjectWithClassLibrary/ClassLibrary/Class1.cs b/test/TestAssets/TestProjects/TestProjectWithClassLibrary/ClassLibrary/Class1.cs new file mode 100644 index 000000000000..534e4f348652 --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectWithClassLibrary/ClassLibrary/Class1.cs @@ -0,0 +1,6 @@ +namespace ClassLibrary +{ + public class Class1 + { + } +} diff --git a/test/TestAssets/TestProjects/TestProjectWithClassLibrary/ClassLibrary/ClassLibrary.csproj b/test/TestAssets/TestProjects/TestProjectWithClassLibrary/ClassLibrary/ClassLibrary.csproj new file mode 100644 index 000000000000..2303a94718ad --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectWithClassLibrary/ClassLibrary/ClassLibrary.csproj @@ -0,0 +1,9 @@ + + + + $(CurrentTargetFramework) + enable + enable + + + diff --git a/test/TestAssets/TestProjects/TestProjectWithClassLibrary/TestProject/Program.cs b/test/TestAssets/TestProjects/TestProjectWithClassLibrary/TestProject/Program.cs new file mode 100644 index 000000000000..28a9001705af --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectWithClassLibrary/TestProject/Program.cs @@ -0,0 +1,46 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => new[] { + typeof(TestNodeUpdateMessage) + }; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test0", + DisplayName = "Test0", + Properties = new PropertyBag(new PassedTestNodeStateProperty("OK")), + })); + + context.Complete(); + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/TestProjectWithClassLibrary/TestProject/TestProject.csproj b/test/TestAssets/TestProjects/TestProjectWithClassLibrary/TestProject/TestProject.csproj new file mode 100644 index 000000000000..c895c63161a3 --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectWithClassLibrary/TestProject/TestProject.csproj @@ -0,0 +1,21 @@ + + + + + Exe + $(CurrentTargetFramework) + enable + enable + true + true + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/TestProjectWithClassLibrary/TestProjectWithClassLibrary.sln b/test/TestAssets/TestProjects/TestProjectWithClassLibrary/TestProjectWithClassLibrary.sln new file mode 100644 index 000000000000..c042974108d5 --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectWithClassLibrary/TestProjectWithClassLibrary.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.35712.36 main +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "TestProject\TestProject.csproj", "{4868FD55-C56D-445C-9F83-A063302EC78F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassLibrary", "ClassLibrary\ClassLibrary.csproj", "{729A12AB-4D79-4756-A776-C7BB63D30A4F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4868FD55-C56D-445C-9F83-A063302EC78F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4868FD55-C56D-445C-9F83-A063302EC78F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4868FD55-C56D-445C-9F83-A063302EC78F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4868FD55-C56D-445C-9F83-A063302EC78F}.Release|Any CPU.Build.0 = Release|Any CPU + {729A12AB-4D79-4756-A776-C7BB63D30A4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {729A12AB-4D79-4756-A776-C7BB63D30A4F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {729A12AB-4D79-4756-A776-C7BB63D30A4F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {729A12AB-4D79-4756-A776-C7BB63D30A4F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E2F590CA-47E0-4145-924B-3E398540BA45} + EndGlobalSection +EndGlobal diff --git a/test/TestAssets/TestProjects/TestProjectWithDiscoveredTests/Program.cs b/test/TestAssets/TestProjects/TestProjectWithDiscoveredTests/Program.cs new file mode 100644 index 000000000000..444f5a1db21b --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectWithDiscoveredTests/Program.cs @@ -0,0 +1,46 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => new[] { + typeof(TestNodeUpdateMessage) + }; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test0", + DisplayName = "Test0", + Properties = new PropertyBag(new DiscoveredTestNodeStateProperty()), + })); + + context.Complete(); + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/TestProjectWithDiscoveredTests/TestProject.csproj b/test/TestAssets/TestProjects/TestProjectWithDiscoveredTests/TestProject.csproj new file mode 100644 index 000000000000..0c30c0b8b8cd --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectWithDiscoveredTests/TestProject.csproj @@ -0,0 +1,20 @@ + + + + + $(CurrentTargetFramework) + Exe + + enable + enable + true + + false + false + true + + + + + + diff --git a/test/TestAssets/TestProjects/TestProjectWithMultipleTFMsSolution/TestProject/Program.cs b/test/TestAssets/TestProjects/TestProjectWithMultipleTFMsSolution/TestProject/Program.cs new file mode 100644 index 000000000000..99cfc02234a4 --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectWithMultipleTFMsSolution/TestProject/Program.cs @@ -0,0 +1,90 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +namespace TestProjectWithNetFM +{ + internal class Program + { + public static async Task Main(string[] args) + { + // To attach to the children + ITestApplicationBuilder testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + + ITestApplication testApplication = await testApplicationBuilder.BuildAsync(); + return await testApplication.RunAsync(); + } + } + + public class DummyTestAdapter : ITestFramework, IDataProducer + { + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => new[] { + typeof(TestNodeUpdateMessage) + }; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test0", + DisplayName = "Test0", + Properties = new PropertyBag(new PassedTestNodeStateProperty("OK")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test1", + DisplayName = "Test1", + Properties = new PropertyBag(new SkippedTestNodeStateProperty("Skipped!")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test2", + DisplayName = "Test2", + Properties = new PropertyBag(new FailedTestNodeStateProperty(new Exception("this is a failed test"), "")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test3", + DisplayName = "Test3", + Properties = new PropertyBag(new TimeoutTestNodeStateProperty(new Exception("this is a timeout exception"), "")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test4", + DisplayName = "Test4", + Properties = new PropertyBag(new ErrorTestNodeStateProperty(new Exception("this is an exception"), "")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test5", + DisplayName = "Test5", + Properties = new PropertyBag(new CancelledTestNodeStateProperty(new Exception("this is a cancelled exception"), "")), + })); + + context.Complete(); + } + } +} diff --git a/test/TestAssets/TestProjects/TestProjectWithMultipleTFMsSolution/TestProject/TestProject.csproj b/test/TestAssets/TestProjects/TestProjectWithMultipleTFMsSolution/TestProject/TestProject.csproj new file mode 100644 index 000000000000..36ec6eef25eb --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectWithMultipleTFMsSolution/TestProject/TestProject.csproj @@ -0,0 +1,20 @@ + + + + + Exe + $(CurrentTargetFramework) + enable + enable + false + true + latest + false + true + + + + + + + \ No newline at end of file diff --git a/test/TestAssets/TestProjects/TestProjectWithMultipleTFMsSolution/TestProjectWithMultipleTFMsSolution.sln b/test/TestAssets/TestProjects/TestProjectWithMultipleTFMsSolution/TestProjectWithMultipleTFMsSolution.sln new file mode 100644 index 000000000000..62931ef6461b --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectWithMultipleTFMsSolution/TestProjectWithMultipleTFMsSolution.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35505.181 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "TestProject\TestProject.csproj", "{D2E321F2-3513-99DE-C37E-6D48D15F404D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D2E321F2-3513-99DE-C37E-6D48D15F404D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D2E321F2-3513-99DE-C37E-6D48D15F404D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D2E321F2-3513-99DE-C37E-6D48D15F404D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D2E321F2-3513-99DE-C37E-6D48D15F404D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3D7914D1-7D03-4FFB-8D0F-7FFA6B6BA6A0} + EndGlobalSection +EndGlobal diff --git a/test/TestAssets/TestProjects/TestProjectWithTests/Program.cs b/test/TestAssets/TestProjects/TestProjectWithTests/Program.cs new file mode 100644 index 000000000000..e7d85d197aea --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectWithTests/Program.cs @@ -0,0 +1,53 @@ +using Microsoft.Testing.Platform.Builder; +using Microsoft.Testing.Platform.Capabilities.TestFramework; +using Microsoft.Testing.Platform.Extensions.Messages; +using Microsoft.Testing.Platform.Extensions.TestFramework; + +var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); + +testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter()); + +using var testApplication = await testApplicationBuilder.BuildAsync(); +return await testApplication.RunAsync(); + +public class DummyTestAdapter : ITestFramework, IDataProducer +{ + public string Uid => nameof(DummyTestAdapter); + + public string Version => "2.0.0"; + + public string DisplayName => nameof(DummyTestAdapter); + + public string Description => nameof(DummyTestAdapter); + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Type[] DataTypesProduced => new[] { + typeof(TestNodeUpdateMessage) + }; + + public Task CreateTestSessionAsync(CreateTestSessionContext context) + => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true }); + + public Task CloseTestSessionAsync(CloseTestSessionContext context) + => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true }); + + public async Task ExecuteRequestAsync(ExecuteRequestContext context) + { + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test0", + DisplayName = "Test0", + Properties = new PropertyBag(new PassedTestNodeStateProperty("OK")), + })); + + await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode() + { + Uid = "Test1", + DisplayName = "Test1", + Properties = new PropertyBag(new SkippedTestNodeStateProperty("OK skipped!")), + })); + + context.Complete(); + } +} \ No newline at end of file diff --git a/test/TestAssets/TestProjects/TestProjectWithTests/TestProject.csproj b/test/TestAssets/TestProjects/TestProjectWithTests/TestProject.csproj new file mode 100644 index 000000000000..0c30c0b8b8cd --- /dev/null +++ b/test/TestAssets/TestProjects/TestProjectWithTests/TestProject.csproj @@ -0,0 +1,20 @@ + + + + + $(CurrentTargetFramework) + Exe + + enable + enable + true + + false + false + true + + + + + + diff --git a/test/UnitTests.proj b/test/UnitTests.proj index 884a36255e87..20f9ab0efca4 100644 --- a/test/UnitTests.proj +++ b/test/UnitTests.proj @@ -126,7 +126,7 @@ . $HELIX_CORRELATION_PAYLOAD/t/RunTestsOnHelix.sh;$(HelixPreCommands) PowerShell -ExecutionPolicy ByPass "dotnet nuget locals all -l | ForEach-Object { $_.Split(' ')[1]} | Where-Object{$_ -like '*cache'} | Get-ChildItem -Recurse -File -Filter '*.dat' | Measure";$(HelixPostCommands) PowerShell -ExecutionPolicy ByPass "Get-ChildItem -Recurse -File -Filter '*hangdump.dmp' | Copy-Item -Destination $env:HELIX_WORKITEM_UPLOAD_ROOT";$(HelixPostCommands) - find . -name '*hangdump.dmp' -exec cp {} "$HELIX_WORKITEM_UPLOAD_ROOT" \%3B;$(HelixPostCommands) + find "$HELIX_WORKITEM_UPLOAD_ROOT/.." -name '*hangdump.dmp' -exec cp {} "$HELIX_WORKITEM_UPLOAD_ROOT" \%3B;$(HelixPostCommands) $(RepoRoot)artifacts\bin\redist\$(Configuration)\dotnet $(Version) $(RepoRoot)artifacts\bin\Microsoft.DotNet.MSBuildSdkResolver diff --git a/test/dotnet-build.Tests/GivenDotnetBuildBuildsCsproj.cs b/test/dotnet-build.Tests/GivenDotnetBuildBuildsCsproj.cs index ea4268d5245d..06b9681ff173 100644 --- a/test/dotnet-build.Tests/GivenDotnetBuildBuildsCsproj.cs +++ b/test/dotnet-build.Tests/GivenDotnetBuildBuildsCsproj.cs @@ -4,6 +4,7 @@ #nullable disable using System.CommandLine; +using Microsoft.DotNet.Configurer; namespace Microsoft.DotNet.Cli.Build.Tests { @@ -379,7 +380,7 @@ public void It_resolves_analyzers_targeting_mulitple_roslyn_versions(string comp static readonly List nugetRoots = new() { TestContext.Current.NuGetCachePath, - Path.Combine(FileConstants.UserProfileFolder, ".dotnet", "NuGetFallbackFolder") + Path.Combine(CliFolderPathCalculator.DotnetHomePath, ".dotnet", "NuGetFallbackFolder") }; static string RelativeNuGetPath(string absoluteNuGetPath) diff --git a/test/dotnet-list-package.Tests/GivenDotnetListPackage.cs b/test/dotnet-list-package.Tests/GivenDotnetListPackage.cs index 21255a917c06..025dcb71a9c2 100644 --- a/test/dotnet-list-package.Tests/GivenDotnetListPackage.cs +++ b/test/dotnet-list-package.Tests/GivenDotnetListPackage.cs @@ -119,6 +119,7 @@ public void ItRunOnSolution() .And.NotHaveStdErr(); new ListPackageCommand(Log) + .WithProject("App.sln") .WithWorkingDirectory(projectDirectory) .Execute() .Should() diff --git a/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenLegacyCommandIsUsed_common.Linux.verified.txt b/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenLegacyCommandIsUsed_common.Linux.verified.txt index 593935c27256..dd70e3a642a2 100644 --- a/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenLegacyCommandIsUsed_common.Linux.verified.txt +++ b/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenLegacyCommandIsUsed_common.Linux.verified.txt @@ -1,47 +1,25 @@ Warning: use of 'dotnet new --list' is deprecated. Use 'dotnet new list' instead. For more information, run: dotnet new list -h - These templates matched your input: - -Template Name Short Name Language Tags --------------------------------------------- ---------------------------- ---------- ---------------------------------- -API Controller apicontroller [C#] Web/ASP.NET -ASP.NET Core Empty web [C#],F# Web/Empty -ASP.NET Core gRPC Service grpc [C#] Web/gRPC/API/Service -ASP.NET Core Web API webapi [C#],F# Web/Web API/API/Service/WebAPI -ASP.NET Core Web API (native AOT) webapiaot [C#] Web/Web API/API/Service -ASP.NET Core Web App (Model-View-Controller) mvc [C#],F# Web/MVC -ASP.NET Core Web App (Razor Pages) webapp,razor [C#] Web/MVC/Razor Pages -Blazor Server App blazorserver [C#] Web/Blazor -Blazor Web App blazor [C#] Web/Blazor/WebAssembly -Blazor WebAssembly Standalone App blazorwasm [C#] Web/Blazor/WebAssembly/PWA -Class Library classlib [C#],F#,VB Common/Library -Console App console [C#],F#,VB Common/Console -dotnet gitattributes file gitattributes,.gitattributes Config -dotnet gitignore file gitignore,.gitignore Config -Dotnet local tool manifest file tool-manifest Config -EditorConfig file editorconfig,.editorconfig Config -global.json file globaljson,global.json Config -MSBuild Directory.Build.props file buildprops MSBuild/props -MSBuild Directory.Build.targets file buildtargets MSBuild/props -MSBuild Directory.Packages.props file packagesprops MSBuild/packages/props/CPM -MSTest Playwright Test Project mstest-playwright [C#] Test/MSTest/Playwright/Desktop/Web -MSTest Test Class mstest-class [C#],F#,VB Test/MSTest -MSTest Test Project mstest [C#],F#,VB Test/MSTest/Desktop/Web -MVC Controller mvccontroller [C#] Web/ASP.NET -MVC ViewImports viewimports [C#] Web/ASP.NET -MVC ViewStart viewstart [C#] Web/ASP.NET -NuGet Config nugetconfig,nuget.config Config -NUnit 3 Test Item nunit-test [C#],F#,VB Test/NUnit -NUnit 3 Test Project nunit [C#],F#,VB Test/NUnit/Desktop/Web -NUnit Playwright Test Project nunit-playwright [C#] Test/NUnit/Playwright/Desktop/Web -Protocol Buffer File proto Web/gRPC -Razor Class Library razorclasslib [C#] Web/Razor/Library -Razor Component razorcomponent [C#] Web/ASP.NET -Razor Page page [C#] Web/ASP.NET -Razor View view [C#] Web/ASP.NET -Solution File sln,solution Solution -Web Config webconfig Config -Worker Service worker [C#],F# Common/Worker/Web -xUnit Test Project xunit [C#],F#,VB Test/xUnit/Desktop/Web +Template +API +ASP.NET +Blazor +Class +Console +dotnet +Dotnet +EditorConfig +global.json +MSBuild +MSTest +MVC +NuGet +NUnit +Protocol +Razor +Solution +Web +Worker +xUnit diff --git a/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenLegacyCommandIsUsed_common.OSX.verified.txt b/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenLegacyCommandIsUsed_common.OSX.verified.txt index 5c619748b23f..dd70e3a642a2 100644 --- a/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenLegacyCommandIsUsed_common.OSX.verified.txt +++ b/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenLegacyCommandIsUsed_common.OSX.verified.txt @@ -1,47 +1,25 @@ Warning: use of 'dotnet new --list' is deprecated. Use 'dotnet new list' instead. For more information, run: dotnet new list -h - These templates matched your input: - -Template Name Short Name Language Tags --------------------------------------------- ---------------------------- ---------- ---------------------------------- -API Controller apicontroller [C#] Web/ASP.NET -ASP.NET Core Empty web [C#],F# Web/Empty -ASP.NET Core gRPC Service grpc [C#] Web/gRPC/API/Service -ASP.NET Core Web API webapi [C#],F# Web/Web API/API/Service/WebAPI -ASP.NET Core Web API (native AOT) webapiaot [C#] Web/Web API/API/Service -ASP.NET Core Web App (Model-View-Controller) mvc [C#],F# Web/MVC -ASP.NET Core Web App (Razor Pages) webapp,razor [C#] Web/MVC/Razor Pages -Blazor Server App blazorserver [C#] Web/Blazor -Blazor Web App blazor [C#] Web/Blazor/WebAssembly -Blazor WebAssembly Standalone App blazorwasm [C#] Web/Blazor/WebAssembly/PWA -Class Library classlib [C#],F#,VB Common/Library -Console App console [C#],F#,VB Common/Console -dotnet gitattributes file gitattributes,.gitattributes Config -dotnet gitignore file gitignore,.gitignore Config -Dotnet local tool manifest file tool-manifest Config -EditorConfig file editorconfig,.editorconfig Config -global.json file globaljson,global.json Config -MSBuild Directory.Build.props file buildprops MSBuild/props -MSBuild Directory.Build.targets file buildtargets MSBuild/props -MSBuild Directory.Packages.props file packagesprops MSBuild/packages/props/CPM -MSTest Playwright Test Project mstest-playwright [C#] Test/MSTest/Playwright/Desktop/Web -MSTest Test Class mstest-class [C#],F#,VB Test/MSTest -MSTest Test Project mstest [C#],F#,VB Test/MSTest/Desktop/Web -MVC Controller mvccontroller [C#] Web/ASP.NET -MVC ViewImports viewimports [C#] Web/ASP.NET -MVC ViewStart viewstart [C#] Web/ASP.NET -NuGet Config nugetconfig,nuget.config Config -NUnit 3 Test Item nunit-test [C#],F#,VB Test/NUnit -NUnit 3 Test Project nunit [C#],F#,VB Test/NUnit/Desktop/Web -NUnit Playwright Test Project nunit-playwright [C#] Test/NUnit/Playwright/Desktop/Web -Protocol Buffer File proto Web/gRPC -Razor Class Library razorclasslib [C#] Web/Razor/Library -Razor Component razorcomponent [C#] Web/ASP.NET -Razor Page page [C#] Web/ASP.NET -Razor View view [C#] Web/ASP.NET -Solution File sln,solution Solution -Web Config webconfig Config -Worker Service worker [C#],F# Common/Worker/Web -xUnit Test Project xunit [C#],F#,VB Test/xUnit/Desktop/Web \ No newline at end of file +Template +API +ASP.NET +Blazor +Class +Console +dotnet +Dotnet +EditorConfig +global.json +MSBuild +MSTest +MVC +NuGet +NUnit +Protocol +Razor +Solution +Web +Worker +xUnit diff --git a/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenLegacyCommandIsUsed_common.Windows.verified.txt b/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenLegacyCommandIsUsed_common.Windows.verified.txt index ac3a91b3919c..4512e81c6be1 100644 --- a/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenLegacyCommandIsUsed_common.Windows.verified.txt +++ b/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenLegacyCommandIsUsed_common.Windows.verified.txt @@ -1,54 +1,27 @@ Warning: use of 'dotnet new --list' is deprecated. Use 'dotnet new list' instead. For more information, run: dotnet new list -h - These templates matched your input: - -Template Name Short Name Language Tags --------------------------------------------- ---------------------------- ---------- ---------------------------------- -API Controller apicontroller [C#] Web/ASP.NET -ASP.NET Core Empty web [C#],F# Web/Empty -ASP.NET Core gRPC Service grpc [C#] Web/gRPC/API/Service -ASP.NET Core Web API webapi [C#],F# Web/Web API/API/Service/WebAPI -ASP.NET Core Web API (native AOT) webapiaot [C#] Web/Web API/API/Service -ASP.NET Core Web App (Model-View-Controller) mvc [C#],F# Web/MVC -ASP.NET Core Web App (Razor Pages) webapp,razor [C#] Web/MVC/Razor Pages -Blazor Server App blazorserver [C#] Web/Blazor -Blazor Web App blazor [C#] Web/Blazor/WebAssembly -Blazor WebAssembly Standalone App blazorwasm [C#] Web/Blazor/WebAssembly/PWA -Class Library classlib [C#],F#,VB Common/Library -Console App console [C#],F#,VB Common/Console -dotnet gitattributes file gitattributes,.gitattributes Config -dotnet gitignore file gitignore,.gitignore Config -Dotnet local tool manifest file tool-manifest Config -EditorConfig file editorconfig,.editorconfig Config -global.json file globaljson,global.json Config -MSBuild Directory.Build.props file buildprops MSBuild/props -MSBuild Directory.Build.targets file buildtargets MSBuild/props -MSBuild Directory.Packages.props file packagesprops MSBuild/packages/props/CPM -MSTest Playwright Test Project mstest-playwright [C#] Test/MSTest/Playwright/Desktop/Web -MSTest Test Class mstest-class [C#],F#,VB Test/MSTest -MSTest Test Project mstest [C#],F#,VB Test/MSTest/Desktop/Web -MVC Controller mvccontroller [C#] Web/ASP.NET -MVC ViewImports viewimports [C#] Web/ASP.NET -MVC ViewStart viewstart [C#] Web/ASP.NET -NuGet Config nugetconfig,nuget.config Config -NUnit 3 Test Item nunit-test [C#],F#,VB Test/NUnit -NUnit 3 Test Project nunit [C#],F#,VB Test/NUnit/Desktop/Web -NUnit Playwright Test Project nunit-playwright [C#] Test/NUnit/Playwright/Desktop/Web -Protocol Buffer File proto Web/gRPC -Razor Class Library razorclasslib [C#] Web/Razor/Library -Razor Component razorcomponent [C#] Web/ASP.NET -Razor Page page [C#] Web/ASP.NET -Razor View view [C#] Web/ASP.NET -Solution File sln,solution Solution -Web Config webconfig Config -Windows Forms App winforms [C#],VB Common/WinForms -Windows Forms Class Library winformslib [C#],VB Common/WinForms -Windows Forms Control Library winformscontrollib [C#],VB Common/WinForms -Worker Service worker [C#],F# Common/Worker/Web -WPF Application wpf [C#],VB Common/WPF -WPF Class Library wpflib [C#],VB Common/WPF -WPF Custom Control Library wpfcustomcontrollib [C#],VB Common/WPF -WPF User Control Library wpfusercontrollib [C#],VB Common/WPF -xUnit Test Project xunit [C#],F#,VB Test/xUnit/Desktop/Web +Template +API +ASP.NET +Blazor +Class +Console +dotnet +Dotnet +EditorConfig +global.json +MSBuild +MSTest +MVC +NuGet +NUnit +Protocol +Razor +Solution +Web +Windows +Worker +WPF +xUnit diff --git a/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenListCommandIsUsed.Linux.verified.txt b/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenListCommandIsUsed.Linux.verified.txt index 9cf877f31f40..a13980ba9ef9 100644 --- a/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenListCommandIsUsed.Linux.verified.txt +++ b/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenListCommandIsUsed.Linux.verified.txt @@ -1,43 +1,22 @@ These templates matched your input: - -Template Name Short Name Language Tags --------------------------------------------- ---------------------------- ---------- ---------------------------------- -API Controller apicontroller [C#] Web/ASP.NET -ASP.NET Core Empty web [C#],F# Web/Empty -ASP.NET Core gRPC Service grpc [C#] Web/gRPC/API/Service -ASP.NET Core Web API webapi [C#],F# Web/Web API/API/Service/WebAPI -ASP.NET Core Web API (native AOT) webapiaot [C#] Web/Web API/API/Service -ASP.NET Core Web App (Model-View-Controller) mvc [C#],F# Web/MVC -ASP.NET Core Web App (Razor Pages) webapp,razor [C#] Web/MVC/Razor Pages -Blazor Server App blazorserver [C#] Web/Blazor -Blazor Web App blazor [C#] Web/Blazor/WebAssembly -Blazor WebAssembly Standalone App blazorwasm [C#] Web/Blazor/WebAssembly/PWA -Class Library classlib [C#],F#,VB Common/Library -Console App console [C#],F#,VB Common/Console -dotnet gitattributes file gitattributes,.gitattributes Config -dotnet gitignore file gitignore,.gitignore Config -Dotnet local tool manifest file tool-manifest Config -EditorConfig file editorconfig,.editorconfig Config -global.json file globaljson,global.json Config -MSBuild Directory.Build.props file buildprops MSBuild/props -MSBuild Directory.Build.targets file buildtargets MSBuild/props -MSBuild Directory.Packages.props file packagesprops MSBuild/packages/props/CPM -MSTest Playwright Test Project mstest-playwright [C#] Test/MSTest/Playwright/Desktop/Web -MSTest Test Class mstest-class [C#],F#,VB Test/MSTest -MSTest Test Project mstest [C#],F#,VB Test/MSTest/Desktop/Web -MVC Controller mvccontroller [C#] Web/ASP.NET -MVC ViewImports viewimports [C#] Web/ASP.NET -MVC ViewStart viewstart [C#] Web/ASP.NET -NuGet Config nugetconfig,nuget.config Config -NUnit 3 Test Item nunit-test [C#],F#,VB Test/NUnit -NUnit 3 Test Project nunit [C#],F#,VB Test/NUnit/Desktop/Web -NUnit Playwright Test Project nunit-playwright [C#] Test/NUnit/Playwright/Desktop/Web -Protocol Buffer File proto Web/gRPC -Razor Class Library razorclasslib [C#] Web/Razor/Library -Razor Component razorcomponent [C#] Web/ASP.NET -Razor Page page [C#] Web/ASP.NET -Razor View view [C#] Web/ASP.NET -Solution File sln,solution Solution -Web Config webconfig Config -Worker Service worker [C#],F# Common/Worker/Web -xUnit Test Project xunit [C#],F#,VB Test/xUnit/Desktop/Web +Template +API +ASP.NET +Blazor +Class +Console +dotnet +Dotnet +EditorConfig +global.json +MSBuild +MSTest +MVC +NuGet +NUnit +Protocol +Razor +Solution +Web +Worker +xUnit diff --git a/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenListCommandIsUsed.OSX.verified.txt b/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenListCommandIsUsed.OSX.verified.txt index 5f864b5ef228..a13980ba9ef9 100644 --- a/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenListCommandIsUsed.OSX.verified.txt +++ b/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenListCommandIsUsed.OSX.verified.txt @@ -1,43 +1,22 @@ These templates matched your input: - -Template Name Short Name Language Tags --------------------------------------------- ---------------------------- ---------- ---------------------------------- -API Controller apicontroller [C#] Web/ASP.NET -ASP.NET Core Empty web [C#],F# Web/Empty -ASP.NET Core gRPC Service grpc [C#] Web/gRPC/API/Service -ASP.NET Core Web API webapi [C#],F# Web/Web API/API/Service/WebAPI -ASP.NET Core Web API (native AOT) webapiaot [C#] Web/Web API/API/Service -ASP.NET Core Web App (Model-View-Controller) mvc [C#],F# Web/MVC -ASP.NET Core Web App (Razor Pages) webapp,razor [C#] Web/MVC/Razor Pages -Blazor Server App blazorserver [C#] Web/Blazor -Blazor Web App blazor [C#] Web/Blazor/WebAssembly -Blazor WebAssembly Standalone App blazorwasm [C#] Web/Blazor/WebAssembly/PWA -Class Library classlib [C#],F#,VB Common/Library -Console App console [C#],F#,VB Common/Console -dotnet gitattributes file gitattributes,.gitattributes Config -dotnet gitignore file gitignore,.gitignore Config -Dotnet local tool manifest file tool-manifest Config -EditorConfig file editorconfig,.editorconfig Config -global.json file globaljson,global.json Config -MSBuild Directory.Build.props file buildprops MSBuild/props -MSBuild Directory.Build.targets file buildtargets MSBuild/props -MSBuild Directory.Packages.props file packagesprops MSBuild/packages/props/CPM -MSTest Playwright Test Project mstest-playwright [C#] Test/MSTest/Playwright/Desktop/Web -MSTest Test Class mstest-class [C#],F#,VB Test/MSTest -MSTest Test Project mstest [C#],F#,VB Test/MSTest/Desktop/Web -MVC Controller mvccontroller [C#] Web/ASP.NET -MVC ViewImports viewimports [C#] Web/ASP.NET -MVC ViewStart viewstart [C#] Web/ASP.NET -NuGet Config nugetconfig,nuget.config Config -NUnit 3 Test Item nunit-test [C#],F#,VB Test/NUnit -NUnit 3 Test Project nunit [C#],F#,VB Test/NUnit/Desktop/Web -NUnit Playwright Test Project nunit-playwright [C#] Test/NUnit/Playwright/Desktop/Web -Protocol Buffer File proto Web/gRPC -Razor Class Library razorclasslib [C#] Web/Razor/Library -Razor Component razorcomponent [C#] Web/ASP.NET -Razor Page page [C#] Web/ASP.NET -Razor View view [C#] Web/ASP.NET -Solution File sln,solution Solution -Web Config webconfig Config -Worker Service worker [C#],F# Common/Worker/Web -xUnit Test Project xunit [C#],F#,VB Test/xUnit/Desktop/Web \ No newline at end of file +Template +API +ASP.NET +Blazor +Class +Console +dotnet +Dotnet +EditorConfig +global.json +MSBuild +MSTest +MVC +NuGet +NUnit +Protocol +Razor +Solution +Web +Worker +xUnit diff --git a/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenListCommandIsUsed.Windows.verified.txt b/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenListCommandIsUsed.Windows.verified.txt index 29aefcf207a9..f5aee20c268c 100644 --- a/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenListCommandIsUsed.Windows.verified.txt +++ b/test/dotnet-new.Tests/Approvals/DotnetNewListTests.BasicTest_WhenListCommandIsUsed.Windows.verified.txt @@ -1,50 +1,24 @@ These templates matched your input: - -Template Name Short Name Language Tags --------------------------------------------- ---------------------------- ---------- ---------------------------------- -API Controller apicontroller [C#] Web/ASP.NET -ASP.NET Core Empty web [C#],F# Web/Empty -ASP.NET Core gRPC Service grpc [C#] Web/gRPC/API/Service -ASP.NET Core Web API webapi [C#],F# Web/Web API/API/Service/WebAPI -ASP.NET Core Web API (native AOT) webapiaot [C#] Web/Web API/API/Service -ASP.NET Core Web App (Model-View-Controller) mvc [C#],F# Web/MVC -ASP.NET Core Web App (Razor Pages) webapp,razor [C#] Web/MVC/Razor Pages -Blazor Server App blazorserver [C#] Web/Blazor -Blazor Web App blazor [C#] Web/Blazor/WebAssembly -Blazor WebAssembly Standalone App blazorwasm [C#] Web/Blazor/WebAssembly/PWA -Class Library classlib [C#],F#,VB Common/Library -Console App console [C#],F#,VB Common/Console -dotnet gitattributes file gitattributes,.gitattributes Config -dotnet gitignore file gitignore,.gitignore Config -Dotnet local tool manifest file tool-manifest Config -EditorConfig file editorconfig,.editorconfig Config -global.json file globaljson,global.json Config -MSBuild Directory.Build.props file buildprops MSBuild/props -MSBuild Directory.Build.targets file buildtargets MSBuild/props -MSBuild Directory.Packages.props file packagesprops MSBuild/packages/props/CPM -MSTest Playwright Test Project mstest-playwright [C#] Test/MSTest/Playwright/Desktop/Web -MSTest Test Class mstest-class [C#],F#,VB Test/MSTest -MSTest Test Project mstest [C#],F#,VB Test/MSTest/Desktop/Web -MVC Controller mvccontroller [C#] Web/ASP.NET -MVC ViewImports viewimports [C#] Web/ASP.NET -MVC ViewStart viewstart [C#] Web/ASP.NET -NuGet Config nugetconfig,nuget.config Config -NUnit 3 Test Item nunit-test [C#],F#,VB Test/NUnit -NUnit 3 Test Project nunit [C#],F#,VB Test/NUnit/Desktop/Web -NUnit Playwright Test Project nunit-playwright [C#] Test/NUnit/Playwright/Desktop/Web -Protocol Buffer File proto Web/gRPC -Razor Class Library razorclasslib [C#] Web/Razor/Library -Razor Component razorcomponent [C#] Web/ASP.NET -Razor Page page [C#] Web/ASP.NET -Razor View view [C#] Web/ASP.NET -Solution File sln,solution Solution -Web Config webconfig Config -Windows Forms App winforms [C#],VB Common/WinForms -Windows Forms Class Library winformslib [C#],VB Common/WinForms -Windows Forms Control Library winformscontrollib [C#],VB Common/WinForms -Worker Service worker [C#],F# Common/Worker/Web -WPF Application wpf [C#],VB Common/WPF -WPF Class Library wpflib [C#],VB Common/WPF -WPF Custom Control Library wpfcustomcontrollib [C#],VB Common/WPF -WPF User Control Library wpfusercontrollib [C#],VB Common/WPF -xUnit Test Project xunit [C#],F#,VB Test/xUnit/Desktop/Web +Template +API +ASP.NET +Blazor +Class +Console +dotnet +Dotnet +EditorConfig +global.json +MSBuild +MSTest +MVC +NuGet +NUnit +Protocol +Razor +Solution +Web +Windows +Worker +WPF +xUnit diff --git a/test/dotnet-new.Tests/CommonTemplatesTests.cs b/test/dotnet-new.Tests/CommonTemplatesTests.cs index 27bd96e1cfea..8076453d7a1c 100644 --- a/test/dotnet-new.Tests/CommonTemplatesTests.cs +++ b/test/dotnet-new.Tests/CommonTemplatesTests.cs @@ -166,8 +166,7 @@ public async Task AotVariants(string name, string language) { // template framework needs to be hardcoded here during the major version transition. string currentDefaultFramework = $"net{Environment.Version.Major}.{Environment.Version.Minor}"; - // Templates have not been updated to net10.0 yet "net9.0"; - // string currentDefaultFramework = "net9.0"; + // string currentDefaultFramework = "net10.0"; string workingDir = CreateTemporaryFolder(folderName: $"{name}-{language}"); string outputDir = "MyProject"; @@ -336,8 +335,7 @@ public async Task FeaturesSupport( bool supportsImplicitUsings, bool supportsFileScopedNs) { - // Templates have not been updated to net10.0 yet "net9.0"; - // string currentDefaultFramework = "net9.0"; + // string currentDefaultFramework = "net10.0"; string currentDefaultFramework = $"net{Environment.Version.Major}.{Environment.Version.Minor}"; string workingDir = CreateTemporaryFolder(folderName: $"{name}-{langVersion ?? "null"}-{framework ?? "null"}"); diff --git a/test/dotnet-new.Tests/DotnetNewDebugOptionsTests.cs b/test/dotnet-new.Tests/DotnetNewDebugOptionsTests.cs index 23f31e1ce198..cd9fe52064fa 100644 --- a/test/dotnet-new.Tests/DotnetNewDebugOptionsTests.cs +++ b/test/dotnet-new.Tests/DotnetNewDebugOptionsTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Configurer; namespace Microsoft.DotNet.Cli.New.IntegrationTests { @@ -93,7 +94,7 @@ public Task CanShowConfigWithDebugShowConfig() public void DoesNotCreateCacheWhenVirtualHiveIsUsed() { string home = CreateTemporaryFolder(folderName: "Home"); - string envVariable = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "USERPROFILE" : "HOME"; + string envVariable = CliFolderPathCalculator.DotnetHomePath; new DotnetNewCommand(_log, "--debug:ephemeral-hive") .WithoutCustomHive() diff --git a/test/dotnet-new.Tests/DotnetNewInstallTests.cs b/test/dotnet-new.Tests/DotnetNewInstallTests.cs index a7bca8cf6e46..b1cb114635c6 100644 --- a/test/dotnet-new.Tests/DotnetNewInstallTests.cs +++ b/test/dotnet-new.Tests/DotnetNewInstallTests.cs @@ -42,21 +42,22 @@ public void CanInstallRemoteNuGetPackage(string commandName) } [Theory] - [InlineData("-i")] - [InlineData("install")] - public void CanInstallRemoteNuGetPackage_LatestVariations(string commandName) + [InlineData("::")] + [InlineData("@")] + public void CanInstallRemoteNuGetPackage_LatestVariations(string separator) { + var commandName = "install"; CommandResult command1 = new DotnetNewCommand(_log, commandName, "Microsoft.DotNet.Common.ProjectTemplates.5.0") .WithCustomHive(CreateTemporaryFolder(folderName: "Home")) .WithWorkingDirectory(CreateTemporaryFolder()) .Execute(); - CommandResult command2 = new DotnetNewCommand(_log, commandName, "Microsoft.DotNet.Common.ProjectTemplates.5.0::") + CommandResult command2 = new DotnetNewCommand(_log, commandName, $"Microsoft.DotNet.Common.ProjectTemplates.5.0{separator}") .WithCustomHive(CreateTemporaryFolder(folderName: "Home")) .WithWorkingDirectory(CreateTemporaryFolder()) .Execute(); - CommandResult command3 = new DotnetNewCommand(_log, commandName, "Microsoft.DotNet.Common.ProjectTemplates.5.0::*") + CommandResult command3 = new DotnetNewCommand(_log, commandName, $"Microsoft.DotNet.Common.ProjectTemplates.5.0{separator}*") .WithCustomHive(CreateTemporaryFolder(folderName: "Home")) .WithWorkingDirectory(CreateTemporaryFolder()) .Execute(); diff --git a/test/dotnet-new.Tests/DotnetNewListTests.Approval.cs b/test/dotnet-new.Tests/DotnetNewListTests.Approval.cs index 985d1b07932b..d296b7c9fe81 100644 --- a/test/dotnet-new.Tests/DotnetNewListTests.Approval.cs +++ b/test/dotnet-new.Tests/DotnetNewListTests.Approval.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.DotNet.Cli.Utils; @@ -7,8 +7,7 @@ namespace Microsoft.DotNet.Cli.New.IntegrationTests { public partial class DotnetNewListTests { -#pragma warning disable xUnit1004 // Test methods should not be skipped - [Theory(Skip = "https://github.com/dotnet/sdk/issues/45406")] + [Theory] [InlineData("-l")] [InlineData("--list")] public Task BasicTest_WhenLegacyCommandIsUsed(string commandName) @@ -25,10 +24,11 @@ public Task BasicTest_WhenLegacyCommandIsUsed(string commandName) return Verify(commandResult.StdOut) .UniqueForOSPlatform() .UseTextForParameters("common") - .DisableRequireUniquePrefix(); + .DisableRequireUniquePrefix() + .AddScrubber(ScrubData); } - [Fact(Skip = "https://github.com/dotnet/sdk/issues/45406")] + [Fact] public Task BasicTest_WhenListCommandIsUsed() { CommandResult commandResult = new DotnetNewCommand(_log, "list") @@ -40,9 +40,55 @@ public Task BasicTest_WhenListCommandIsUsed() .Should() .Pass(); - return Verify(commandResult.StdOut).UniqueForOSPlatform(); + return Verify(commandResult.StdOut) + .UniqueForOSPlatform() + .AddScrubber(ScrubData); + } + + // We're listing the built in templates which we don't control so this fails often + // By scrubbing out the last three columns and then taking only the unique first words + // we can ensure that the list is showing columns and they haven't significantly changed. + // That's the best we can do for validating an output we don't control + private static void ScrubData(StringBuilder input) + { + var lines = input.ToString().Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + var scrubbedLines = new HashSet(); + bool isTable = false; + + foreach (var line in lines) + { + // start trimming whitespace and anything but the first word with the start of the table + if (line.StartsWith("Template Name", StringComparison.Ordinal)) + { + isTable = true; + } + + // We don't want to have to count how many dashes are in the table separator as this can change based on the width of the column + if (line.StartsWith("-----", StringComparison.Ordinal)) + { + continue; + } + + if (isTable) + { + var columns = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + if (columns.Length > 0) + { + scrubbedLines.Add(columns[0]); + } + } + else + { + scrubbedLines.Add(line); + } + } + + input.Clear(); + foreach (var scrubbedLine in scrubbedLines) + { + input.AppendLine(scrubbedLine); + } } -#pragma warning restore xUnit1004 [Fact] public Task Constraints_CanShowMessageIfTemplateGroupIsRestricted() diff --git a/test/dotnet-run.Tests/GivenDotnetRunBuildsCsProj.cs b/test/dotnet-run.Tests/GivenDotnetRunBuildsCsProj.cs index b41612701ee1..527996a4866a 100644 --- a/test/dotnet-run.Tests/GivenDotnetRunBuildsCsProj.cs +++ b/test/dotnet-run.Tests/GivenDotnetRunBuildsCsProj.cs @@ -836,23 +836,61 @@ public void ItIncludesEnvironmentVariablesSpecifiedInLaunchSettings() } [Fact] - public void ItIncludesCommandArgumentsSpecifiedInLaunchSettings() + public void EnvVariablesSpecifiedInLaunchProfileOverrideImplicitlySetVariables() { - var expectedValue = "TestAppCommandLineArguments"; - var secondExpectedValue = "SecondTestAppCommandLineArguments"; var testAppName = "TestAppWithLaunchSettings"; var testInstance = _testAssetsManager.CopyTestAsset(testAppName) .WithSource(); + // Profile2 defines env variable DOTNET_LAUNCH_PROFILE=XYZ and ASPNETCORE_URLS=XYZ + + new DotnetCommand(Log, "run", "-lp", "Profile2") + .WithWorkingDirectory(testInstance.Path) + .Execute() + .Should() + .Pass() + .And + .HaveStdOutContaining("env: DOTNET_LAUNCH_PROFILE=XYZ") + .And + .HaveStdOutContaining("env: ASPNETCORE_URLS=XYZ"); + } + + [Fact] + public void ItIncludesCommandArgumentsSpecifiedInLaunchSettings() + { + var testInstance = _testAssetsManager.CopyTestAsset("TestAppWithLaunchSettings") + .WithSource(); + + // launchSettings.json specifies commandLineArgs="TestAppCommandLineArguments SecondTestAppCommandLineArguments" + new DotnetCommand(Log, "run") .WithWorkingDirectory(testInstance.Path) .Execute() .Should() .Pass() .And - .HaveStdOutContaining(expectedValue) + .HaveStdOutContaining("TestAppCommandLineArguments") .And - .HaveStdOutContaining(secondExpectedValue); + .HaveStdOutContaining("SecondTestAppCommandLineArguments"); + } + + [Fact] + public void ItIgnoresCommandArgumentsSpecifiedInLaunchSettings() + { + var testInstance = _testAssetsManager.CopyTestAsset("TestAppWithLaunchSettings") + .WithSource(); + + // launchSettings.json specifies commandLineArgs="TestAppCommandLineArguments SecondTestAppCommandLineArguments" + + new DotnetCommand(Log, "run", "--no-launch-profile-arguments") + .WithWorkingDirectory(testInstance.Path) + .Execute() + .Should() + .Pass() + .And + .NotHaveStdOutContaining("TestAppCommandLineArguments") + .And + .NotHaveStdOutContaining("SecondTestAppCommandLineArguments"); } [Fact] @@ -874,5 +912,74 @@ public void ItCLIArgsOverrideCommandArgumentsSpecifiedInLaunchSettings() .And .NotHaveStdOutContaining(secondExpectedValue); } + + [Fact] + public void ItIncludesApplicationUrlSpecifiedInLaunchSettings() + { + var testInstance = _testAssetsManager.CopyTestAsset("TestAppWithLaunchSettings") + .WithSource(); + + new DotnetCommand(Log, "run") + .WithWorkingDirectory(testInstance.Path) + .Execute() + .Should() + .Pass() + .And + .HaveStdOutContaining("env: ASPNETCORE_URLS=http://localhost:5000"); + } + + [Theory] + [InlineData("-e")] + [InlineData("--environment")] + public void EnvOptionOverridesCommandArgumentsSpecifiedInLaunchSettings(string optionName) + { + var testInstance = _testAssetsManager.CopyTestAsset("TestAppWithLaunchSettings") + .WithSource(); + + new DotnetCommand(Log, "run", optionName, "MyCoolEnvironmentVariableKey=OverriddenEnvironmentVariableValue") + .WithWorkingDirectory(testInstance.Path) + .Execute() + .Should() + .Pass() + .And + .HaveStdOutContaining("env: MyCoolEnvironmentVariableKey=OverriddenEnvironmentVariableValue"); + } + + [Fact] + public void EnvOptionOverridesImplicitlySetVariables() + { + var testInstance = _testAssetsManager.CopyTestAsset("TestAppWithLaunchSettings") + .WithSource(); + + // + var dotnetLaunchProfile = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + ? "DOTNET_LAUNCH_profile" + : "DOTNET_LAUNCH_PROFILE"; + + new DotnetCommand(Log, "run", "-e", $"{dotnetLaunchProfile}=1", "-e", "ASPNETCORE_URLS=2") + .WithWorkingDirectory(testInstance.Path) + .Execute() + .Should() + .Pass() + .And + .HaveStdOutContaining("env: DOTNET_LAUNCH_PROFILE=1") + .And + .HaveStdOutContaining("env: ASPNETCORE_URLS=2"); + } + + [Fact] + public void EnvOptionNotAppliedToBuild() + { + var testInstance = _testAssetsManager.CopyTestAsset("TestAppWithLaunchSettings") + .WithSource(); + + new DotnetCommand(Log, "run", "-e", "Configuration=XYZ") + .WithWorkingDirectory(testInstance.Path) + .Execute() + .Should() + .Pass() + .And + .HaveStdOutContaining("env: Configuration=XYZ"); + } } } diff --git a/test/dotnet-sln.Tests/GivenDotnetSlnAdd.cs b/test/dotnet-sln.Tests/GivenDotnetSlnAdd.cs index 08db06681412..c4eae1f9e445 100644 --- a/test/dotnet-sln.Tests/GivenDotnetSlnAdd.cs +++ b/test/dotnet-sln.Tests/GivenDotnetSlnAdd.cs @@ -3,7 +3,6 @@ #nullable disable -using Microsoft.DotNet.Cli.Sln.Internal; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Tools; using Microsoft.DotNet.Tools.Common; @@ -14,6 +13,15 @@ namespace Microsoft.DotNet.Cli.Sln.Add.Tests { + public static class ProjectTypeGuids + { + public const string CSharpProjectTypeGuid = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"; + public const string FSharpProjectTypeGuid = "{F2A71F9B-5D33-465A-A702-920D77279786}"; + public const string VBProjectTypeGuid = "{F184B08F-C81C-45F6-A57F-5ABD9991F28F}"; + public const string SolutionFolderGuid = "{2150E333-8FDC-42A3-9474-1A3956D46DE8}"; + public const string SharedProjectGuid = "{D954291E-2A0B-460D-934E-DC6B0785DB48}"; + } + public class GivenDotnetSlnAdd : SdkTest { private Func HelpText = (defaultVal) => $@"Description: diff --git a/test/dotnet-sln.Tests/GivenDotnetSlnList.cs b/test/dotnet-sln.Tests/GivenDotnetSlnList.cs index f462ff1e6042..97ce222a757c 100644 --- a/test/dotnet-sln.Tests/GivenDotnetSlnList.cs +++ b/test/dotnet-sln.Tests/GivenDotnetSlnList.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.DotNet.Cli.Sln.Internal; using Microsoft.DotNet.Tools; using Microsoft.DotNet.Tools.Common; using CommandLocalizableStrings = Microsoft.DotNet.Tools.Sln.LocalizableStrings; @@ -261,5 +260,25 @@ public void WhenProjectsInSolutionFoldersPresentInTheSolutionItListsSolutionFold cmd.Should().Pass(); cmd.StdOut.Should().ContainAll(expectedOutput); } + + [Theory] + [InlineData("sln")] + [InlineData("solution")] + public void WhenSolutionFilterIsPassedItListsProjectsMatching(string solutionCommand) + { + string[] expectedOutput = { $"{CommandLocalizableStrings.ProjectsHeader}", + $"{new string('-', CommandLocalizableStrings.ProjectsHeader.Length)}", + $"{Path.Combine("src", "App", "App.csproj")}" }; + var projectDirectory = _testAssetsManager + .CopyTestAsset("TestAppWithSlnxAndSolutionFilters", identifier: "GivenDotnetSlnList-Filter") + .WithSource() + .Path; + + var cmd = new DotnetCommand(Log) + .WithWorkingDirectory(projectDirectory) + .Execute(solutionCommand, "App.slnf", "list"); + cmd.Should().Pass(); + cmd.StdOut.Should().ContainAll(expectedOutput); + } } } diff --git a/test/dotnet-sln.Tests/GivenDotnetSlnMigrate.cs b/test/dotnet-sln.Tests/GivenDotnetSlnMigrate.cs index 7af7267a2997..f18ac2d7fba5 100644 --- a/test/dotnet-sln.Tests/GivenDotnetSlnMigrate.cs +++ b/test/dotnet-sln.Tests/GivenDotnetSlnMigrate.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.DotNet.Cli.Sln.Internal; using Microsoft.DotNet.Tools; using Microsoft.DotNet.Tools.Common; using CommandLocalizableStrings = Microsoft.DotNet.Tools.Sln.LocalizableStrings; diff --git a/test/dotnet-sln.Tests/dotnet-sln.Tests.csproj b/test/dotnet-sln.Tests/dotnet-sln.Tests.csproj index ad45aa7b7e6c..8b9e3844a891 100644 --- a/test/dotnet-sln.Tests/dotnet-sln.Tests.csproj +++ b/test/dotnet-sln.Tests/dotnet-sln.Tests.csproj @@ -12,7 +12,6 @@ - diff --git a/test/dotnet-test.Tests/GivenDotnetTestBuildsAndDiscoversTests.cs b/test/dotnet-test.Tests/GivenDotnetTestBuildsAndDiscoversTests.cs new file mode 100644 index 000000000000..f416edbcf3dd --- /dev/null +++ b/test/dotnet-test.Tests/GivenDotnetTestBuildsAndDiscoversTests.cs @@ -0,0 +1,151 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using CommandResult = Microsoft.DotNet.Cli.Utils.CommandResult; + +namespace Microsoft.DotNet.Cli.Test.Tests +{ + public class GivenDotnetTestBuildsAndDiscoversTests : SdkTest + { + public GivenDotnetTestBuildsAndDiscoversTests(ITestOutputHelper log) : base(log) + { + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void DiscoverTestProjectWithNoTests_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("TestProjectSolution", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ListTestsOption.Name, TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + Assert.Matches(RegexPatternHelper.GenerateProjectRegexPattern("TestProject", true, "Discovered 0 tests"), result.StdOut); + + result.StdOut + .Should().Contain("Discovered 0 tests."); + } + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void DiscoverMultipleTestProjectsWithNoTests_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MultipleTestProjectSolution", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ListTestsOption.Name, TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + Assert.Matches(RegexPatternHelper.GenerateProjectRegexPattern("TestProject", true, "Discovered 0 tests"), result.StdOut); + Assert.Matches(RegexPatternHelper.GenerateProjectRegexPattern("OtherTestProject", true, "Discovered 0 tests"), result.StdOut); + Assert.Matches(RegexPatternHelper.GenerateProjectRegexPattern("AnotherTestProject", true, "Discovered 0 tests"), result.StdOut); + Assert.Matches(@"Discovered 0 tests.*", result.StdOut); + } + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void DiscoverTestProjectWithTests_ShouldReturnZeroAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("TestProjectWithDiscoveredTests", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ListTestsOption.Name, TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + Assert.Matches(RegexPatternHelper.GenerateProjectRegexPattern("TestProject", true, "Discovered 1 tests", ["Test0"]), result.StdOut); + Assert.Matches(@"Discovered 1 tests.*", result.StdOut); + } + + result.ExitCode.Should().Be(ExitCodes.Success); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void DiscoverMultipleTestProjectsWithTests_ShouldReturnZeroAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MultiTestProjectSolutionWithDiscoveredTests", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ListTestsOption.Name, TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + Assert.Matches(RegexPatternHelper.GenerateProjectRegexPattern("TestProject", true, "Discovered 2 tests", ["Test0", "Test2"]), result.StdOut); + Assert.Matches(RegexPatternHelper.GenerateProjectRegexPattern("OtherTestProject", true, "Discovered 1 tests", ["Test1"]), result.StdOut); + Assert.Matches(@"Discovered 3 tests.*", result.StdOut); + } + + result.ExitCode.Should().Be(ExitCodes.Success); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void DiscoverProjectWithMSTestMetaPackageAndMultipleTFMsWithTests_ShouldReturnZeroAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MSTestMetaPackageProjectWithMultipleTFMsSolution", Guid.NewGuid().ToString()) + .WithSource(); + testInstance.WithTargetFrameworks($"{DotnetVersionHelper.GetPreviousDotnetVersion()};{ToolsetInfo.CurrentTargetFramework}", "TestProject"); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ListTestsOption.Name, TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + Assert.Matches(RegexPatternHelper.GenerateProjectRegexPattern("TestProject", false, "Discovered 3 tests", ["TestMethod1", "TestMethod2", "TestMethod3"]), result.StdOut); + Assert.Matches(RegexPatternHelper.GenerateProjectRegexPattern("TestProject", true, "Discovered 2 tests", ["TestMethod1", "TestMethod3"]), result.StdOut); + } + + result.ExitCode.Should().Be(ExitCodes.Success); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void DiscoverTestProjectsWithHybridModeTestRunners_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("HybridTestRunnerTestProjects", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ListTestsOption.Name, TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + result.StdOut.Should().Contain(Tools.Test.LocalizableStrings.CmdUnsupportedVSTestTestApplicationsDescription); + } + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + } +} diff --git a/test/dotnet-test.Tests/GivenDotnetTestBuildsAndRunsHelp.cs b/test/dotnet-test.Tests/GivenDotnetTestBuildsAndRunsHelp.cs new file mode 100644 index 000000000000..774632f30ec3 --- /dev/null +++ b/test/dotnet-test.Tests/GivenDotnetTestBuildsAndRunsHelp.cs @@ -0,0 +1,63 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using dotnet.Tests; +using CommandResult = Microsoft.DotNet.Cli.Utils.CommandResult; + +namespace Microsoft.DotNet.Cli.Test.Tests +{ + public class GivenDotnetTestBuildsAndRunsHelp : SdkTest + { + public GivenDotnetTestBuildsAndRunsHelp(ITestOutputHelper log) : base(log) + { + } + + [InlineData(Constants.Debug)] + [InlineData(Constants.Release)] + [Theory] + public void RunHelpOnTestProject_ShouldReturnZeroAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("TestProjectSolutionWithTestsAndArtifacts", Guid.NewGuid().ToString()).WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(CliConstants.HelpOptionKey, TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + Assert.Matches(@"Extension options:\s+--[\s\S]*", result.StdOut); + Assert.Matches(@"Options:\s+--[\s\S]*", result.StdOut); + } + + result.ExitCode.Should().Be(ExitCodes.Success); + } + + [InlineData(Constants.Debug)] + [InlineData(Constants.Release)] + [Theory] + public void RunHelpOnMultipleTestProjects_ShouldReturnZeroAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("ProjectSolutionForMultipleTFMs", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(CliConstants.HelpOptionKey, TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + Assert.Matches(@"Extension options:\s+--[\s\S]*", result.StdOut); + Assert.Matches(@"Options:\s+--[\s\S]*", result.StdOut); + + string net9ProjectDllRegex = @"\s+.*\\net9\.0\\TestProjectWithNet9\.dll.*\s+--report-trx\s+--report-trx-filename"; + string net48ProjectExeRegex = @"\s+.*\\net4\.8\\TestProjectWithNetFramework\.exe.*\s+--report-trx\s+--report-trx-filename"; + + Assert.Matches(@$"Unavailable extension options:(?:({net9ProjectDllRegex})|({net48ProjectExeRegex}))(?:({net48ProjectExeRegex})|({net9ProjectDllRegex}))", result.StdOut); + } + + result.ExitCode.Should().Be(ExitCodes.Success); + } + } +} diff --git a/test/dotnet-test.Tests/GivenDotnetTestBuildsAndRunsTestBasedOnGlobbingFilter.cs b/test/dotnet-test.Tests/GivenDotnetTestBuildsAndRunsTestBasedOnGlobbingFilter.cs new file mode 100644 index 000000000000..337b423afc3a --- /dev/null +++ b/test/dotnet-test.Tests/GivenDotnetTestBuildsAndRunsTestBasedOnGlobbingFilter.cs @@ -0,0 +1,92 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text.RegularExpressions; +using dotnet.Tests; +using CommandResult = Microsoft.DotNet.Cli.Utils.CommandResult; + +namespace Microsoft.DotNet.Cli.Test.Tests +{ + public class GivenDotnetTestBuildsAndRunsTestBasedOnGlobbingFilter : SdkTest + { + private const string TestApplicationArgsPattern = @".*(Test application arguments).*"; + + public GivenDotnetTestBuildsAndRunsTestBasedOnGlobbingFilter(ITestOutputHelper log) : base(log) + { + } + + [InlineData(Constants.Debug)] + [InlineData(Constants.Release)] + [Theory] + public void RunTestProjectWithFilterOfDll_ShouldReturnZeroAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("TestProjectWithTests", Guid.NewGuid().ToString()) + .WithSource(); + + new BuildCommand(testInstance) + .Execute() + .Should().Pass(); + + var binDirectory = new FileInfo($"{testInstance.Path}/bin").Directory; + var binDirectoryLastWriteTime = binDirectory?.LastWriteTime; + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.TestModulesFilterOption.Name, "**/bin/**/Debug/net8.0/TestProject.dll", + TestingPlatformOptions.ConfigurationOption.Name, configuration); + + // Assert that the bin folder hasn't been modified + Assert.Equal(binDirectoryLastWriteTime, binDirectory?.LastWriteTime); + + if (!TestContext.IsLocalized()) + { + result.StdOut + .Should().Contain("Test run summary: Passed!") + .And.Contain("total: 2") + .And.Contain("succeeded: 1") + .And.Contain("failed: 0") + .And.Contain("skipped: 1"); + } + + result.ExitCode.Should().Be(ExitCodes.Success); + } + + [InlineData(Constants.Debug)] + [InlineData(Constants.Release)] + [Theory] + public void RunTestProjectWithFilterOfDllWithRootDirectory_ShouldReturnZeroAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("TestProjectWithTests", Guid.NewGuid().ToString()) + .WithSource(); + + new BuildCommand(testInstance) + .Execute() + .Should().Pass(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .WithTraceOutput() + .Execute(TestingPlatformOptions.TestModulesFilterOption.Name, "**/bin/**/Debug/net8.0/TestProject.dll", + TestingPlatformOptions.TestModulesRootDirectoryOption.Name, testInstance.TestRoot, + TestingPlatformOptions.ConfigurationOption.Name, configuration); + + + var testAppArgs = Regex.Matches(result.StdOut!, TestApplicationArgsPattern); + Assert.Contains($"exec {testInstance.TestRoot}\\bin\\Debug\\net8.0\\TestProject.dll", testAppArgs.FirstOrDefault()?.Value); + + if (!TestContext.IsLocalized()) + { + result.StdOut + .Should().Contain("Test run summary: Passed!") + .And.Contain("total: 2") + .And.Contain("succeeded: 1") + .And.Contain("failed: 0") + .And.Contain("skipped: 1"); + } + + result.ExitCode.Should().Be(ExitCodes.Success); + } + } +} diff --git a/test/dotnet-test.Tests/GivenDotnetTestBuildsAndRunsTests.cs b/test/dotnet-test.Tests/GivenDotnetTestBuildsAndRunsTests.cs new file mode 100644 index 000000000000..bd7628ad950d --- /dev/null +++ b/test/dotnet-test.Tests/GivenDotnetTestBuildsAndRunsTests.cs @@ -0,0 +1,260 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using CommandResult = Microsoft.DotNet.Cli.Utils.CommandResult; + +namespace Microsoft.DotNet.Cli.Test.Tests +{ + public class GivenDotnetTestBuildsAndRunsTests : SdkTest + { + public GivenDotnetTestBuildsAndRunsTests(ITestOutputHelper log) : base(log) + { + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunTestProjectWithNoTests_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("TestProjectSolution", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + result.StdOut + .Should().Contain("Test run summary: Zero tests ran") + .And.Contain("total: 0") + .And.Contain("succeeded: 0") + .And.Contain("failed: 0") + .And.Contain("skipped: 0"); + } + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunMultipleTestProjectsWithNoTests_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MultipleTestProjectSolution", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + result.StdOut + .Should().Contain("Test run summary: Zero tests ran") + .And.Contain("total: 0") + .And.Contain("succeeded: 0") + .And.Contain("failed: 0") + .And.Contain("skipped: 0"); + } + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunTestProjectWithTests_ShouldReturnZeroAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("TestProjectWithTests", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + result.StdOut + .Should().Contain("Test run summary: Passed!") + .And.Contain("skipped Test1") + .And.Contain("total: 2") + .And.Contain("succeeded: 1") + .And.Contain("failed: 0") + .And.Contain("skipped: 1"); + } + + result.ExitCode.Should().Be(ExitCodes.Success); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunMultipleTestProjectsWithFailingTests_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MultiTestProjectSolutionWithTests", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + result.StdOut + .Should().Contain("Test run summary: Failed!") + .And.Contain("total: 5") + .And.Contain("succeeded: 2") + .And.Contain("failed: 1") + .And.Contain("skipped: 2"); + } + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunMultipleTestProjectsWithDifferentFailures_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MultiTestProjectSolutionWithDifferentFailures", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute("--minimum-expected-tests 2", + TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + Assert.Matches(RegexPatternHelper.GenerateProjectRegexPattern("TestProject", "failed", true, "8"), result.StdOut); + Assert.Matches(RegexPatternHelper.GenerateProjectRegexPattern("OtherTestProject", "failed", true, "2"), result.StdOut); + Assert.Matches(RegexPatternHelper.GenerateProjectRegexPattern("AnotherTestProject", "failed", true, "9"), result.StdOut); + + result.StdOut + .Should().Contain("Test run summary: Failed!") + .And.Contain("total: 4") + .And.Contain("succeeded: 2") + .And.Contain("failed: 1") + .And.Contain("skipped: 1"); + } + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunTestProjectsWithHybridModeTestRunners_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("HybridTestRunnerTestProjects", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + result.StdOut.Should().Contain(Tools.Test.LocalizableStrings.CmdUnsupportedVSTestTestApplicationsDescription); + } + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunOnEmptyFolder_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("EmptyFolder", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + result.StdOut.Should().Contain(Tools.Test.LocalizableStrings.CmdNoProjectOrSolutionFileErrorDescription); + } + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunOnMultipleProjectFoldersWithoutSolutionFile_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MultipleTestProjectsWithoutSolution", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + result.StdOut.Should().Contain(Tools.Test.LocalizableStrings.CmdNoProjectOrSolutionFileErrorDescription); + } + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunOnProjectWithSolutionFile_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("TestProjectFileAndSolutionFile", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + result.StdOut.Should().Contain(Tools.Test.LocalizableStrings.CmdMultipleProjectOrSolutionFilesErrorDescription); + } + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunOnProjectWithClassLibrary_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("TestProjectWithClassLibrary", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + result.StdOut + .Should().Contain("Test run summary: Passed!") + .And.Contain("total: 1") + .And.Contain("succeeded: 1") + .And.Contain("failed: 0") + .And.Contain("skipped: 0"); + } + + result.ExitCode.Should().Be(ExitCodes.Success); + } + } +} diff --git a/test/dotnet-test.Tests/GivenDotnetTestBuildsAndRunsTestsForMultipleTFMs.cs b/test/dotnet-test.Tests/GivenDotnetTestBuildsAndRunsTestsForMultipleTFMs.cs new file mode 100644 index 000000000000..cf15cb49018c --- /dev/null +++ b/test/dotnet-test.Tests/GivenDotnetTestBuildsAndRunsTestsForMultipleTFMs.cs @@ -0,0 +1,137 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text.RegularExpressions; +using CommandResult = Microsoft.DotNet.Cli.Utils.CommandResult; + +namespace Microsoft.DotNet.Cli.Test.Tests +{ + public class GivenDotnetTestBuildsAndRunsTestsForMultipleTFMs : SdkTest + { + public GivenDotnetTestBuildsAndRunsTestsForMultipleTFMs(ITestOutputHelper log) : base(log) + { + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunMultipleProjectWithDifferentTFMsWithFailingTests_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("ProjectSolutionForMultipleTFMs", Guid.NewGuid().ToString()) + .WithSource(); + testInstance.WithTargetFramework($"{DotnetVersionHelper.GetPreviousDotnetVersion()}", "TestProject"); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + MatchCollection previousDotnetProjectMatches = Regex.Matches(result.StdOut!, RegexPatternHelper.GenerateProjectRegexPattern("TestProject", TestingConstants.Failed, useCurrentVersion: false)); + MatchCollection currentDotnetProjectMatches = Regex.Matches(result.StdOut!, RegexPatternHelper.GenerateProjectRegexPattern("OtherTestProject", TestingConstants.Passed, useCurrentVersion: true)); + + MatchCollection skippedTestsMatches = Regex.Matches(result.StdOut!, "skipped Test2"); + MatchCollection failedTestsMatches = Regex.Matches(result.StdOut!, "failed Test3"); + + Assert.True(previousDotnetProjectMatches.Count > 1); + Assert.True(currentDotnetProjectMatches.Count > 1); + + Assert.Single(failedTestsMatches); + Assert.Multiple(() => Assert.Equal(2, skippedTestsMatches.Count)); + + result.StdOut + .Should().Contain("Test run summary: Failed!") + .And.Contain("total: 5") + .And.Contain("succeeded: 2") + .And.Contain("failed: 1") + .And.Contain("skipped: 2"); + } + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunProjectWithMultipleTFMsWithFailingTests_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("TestProjectWithMultipleTFMsSolution", Guid.NewGuid().ToString()) + .WithSource(); + testInstance.WithTargetFrameworks($"{DotnetVersionHelper.GetPreviousDotnetVersion()};{ToolsetInfo.CurrentTargetFramework}"); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + MatchCollection previousDotnetProjectMatches = Regex.Matches(result.StdOut!, RegexPatternHelper.GenerateProjectRegexPattern("TestProject", TestingConstants.Failed, useCurrentVersion: false)); + MatchCollection currentDotnetProjectMatches = Regex.Matches(result.StdOut!, RegexPatternHelper.GenerateProjectRegexPattern("TestProject", TestingConstants.Failed, useCurrentVersion: true)); + + MatchCollection skippedTestsMatches = Regex.Matches(result.StdOut!, "skipped Test1"); + MatchCollection failedTestsMatches = Regex.Matches(result.StdOut!, "failed Test2"); + MatchCollection timeoutTestsMatches = Regex.Matches(result.StdOut!, @"failed \(canceled\) Test3"); + MatchCollection errorTestsMatches = Regex.Matches(result.StdOut!, "failed Test4"); + MatchCollection canceledTestsMatches = Regex.Matches(result.StdOut!, @"failed \(canceled\) Test5"); + + Assert.True(previousDotnetProjectMatches.Count > 1); + Assert.True(currentDotnetProjectMatches.Count > 1); + + Assert.Multiple(() => Assert.Equal(2, skippedTestsMatches.Count)); + Assert.Multiple(() => Assert.Equal(2, failedTestsMatches.Count)); + Assert.Multiple(() => Assert.Equal(2, timeoutTestsMatches.Count)); + Assert.Multiple(() => Assert.Equal(2, errorTestsMatches.Count)); + Assert.Multiple(() => Assert.Equal(2, skippedTestsMatches.Count)); + + result.StdOut + .Should().Contain("Test run summary: Failed!") + .And.Contain("total: 12") + .And.Contain("succeeded: 2") + .And.Contain("failed: 8") + .And.Contain("skipped: 2"); + } + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunProjectWithMSTestMetaPackageAndMultipleTFMsWithFailingTests_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MSTestMetaPackageProjectWithMultipleTFMsSolution", Guid.NewGuid().ToString()) + .WithSource(); + testInstance.WithTargetFrameworks($"{DotnetVersionHelper.GetPreviousDotnetVersion()};{ToolsetInfo.CurrentTargetFramework}"); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + MatchCollection previousDotnetProjectMatches = Regex.Matches(result.StdOut!, RegexPatternHelper.GenerateProjectRegexPattern("TestProject", TestingConstants.Failed, useCurrentVersion: false)); + MatchCollection currentDotnetProjectMatches = Regex.Matches(result.StdOut!, RegexPatternHelper.GenerateProjectRegexPattern("TestProject", TestingConstants.Failed, useCurrentVersion: true)); + + MatchCollection failedTestsMatches = Regex.Matches(result.StdOut!, "failed TestMethod3"); + + Assert.True(previousDotnetProjectMatches.Count > 1); + Assert.True(currentDotnetProjectMatches.Count > 1); + + Assert.Multiple(() => Assert.Equal(2, failedTestsMatches.Count)); + + result.StdOut + .Should().Contain("Test run summary: Failed!") + .And.Contain("total: 5") + .And.Contain("succeeded: 3") + .And.Contain("failed: 2") + .And.Contain("skipped: 0"); + } + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + } +} diff --git a/test/dotnet-test.Tests/GivenDotnetTestBuildsAndRunsTestsWithArtifacts.cs b/test/dotnet-test.Tests/GivenDotnetTestBuildsAndRunsTestsWithArtifacts.cs new file mode 100644 index 000000000000..ac8d1e3bb55b --- /dev/null +++ b/test/dotnet-test.Tests/GivenDotnetTestBuildsAndRunsTestsWithArtifacts.cs @@ -0,0 +1,83 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.DotNet.Tools.Common; +using CommandResult = Microsoft.DotNet.Cli.Utils.CommandResult; + +namespace Microsoft.DotNet.Cli.Test.Tests +{ + public class GivenDotnetTestBuildsAndRunsTestsWithArtifacts : SdkTest + { + public GivenDotnetTestBuildsAndRunsTestsWithArtifacts(ITestOutputHelper log) : base(log) + { + } + + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunTestProjectWithFailingTestsAndFileArtifacts_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("TestProjectSolutionWithTestsAndArtifacts", Guid.NewGuid().ToString()).WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + Assert.Matches(@".*Test6.*testNodeFile.txt", result.StdOut); + + result.StdOut + .Should().Contain("In process file artifacts") + .And.Contain("file.txt") + .And.Contain("sessionFile.txt"); + + result.StdOut + .Should().Contain("Test run summary: Failed!") + .And.Contain("total: 6") + .And.Contain("succeeded: 1") + .And.Contain("failed: 4") + .And.Contain("skipped: 1"); + } + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunTestProjectWithCodeCoverage_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("TestProjectSolutionWithCodeCoverage", Guid.NewGuid().ToString()).WithSource(); + + // Read MSTestVersion from Versions.props and update the .csproj file + // Search for Versions.props file from the current directory up to the root + string? versionsPropsPath = PathUtility.FindFileInParentDirectories(TestContext.Current.TestExecutionDirectory, $"eng{Path.DirectorySeparatorChar}Versions.props") ?? throw new FileNotFoundException("Versions.props file not found."); + string msTestVersion = testInstance.ReadMSTestVersionFromProps(versionsPropsPath); + testInstance.UpdateProjectFileWithMSTestVersion(Path.Combine($@"{testInstance.Path}{PathUtility.GetDirectorySeparatorChar()}TestProject", "TestProject.csproj"), msTestVersion); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute("--coverage", TestingPlatformOptions.ConfigurationOption.Name, configuration); + + if (!TestContext.IsLocalized()) + { + string pattern = $@"In\sprocess\sfile\sartifacts\sproduced:\s+.*{PathUtility.GetDirectorySeparatorChar()}TestResults{PathUtility.GetDirectorySeparatorChar()}.*\.coverage"; + + Assert.Matches(pattern, result.StdOut); + + result.StdOut + .Should().Contain("Test run summary: Failed!") + .And.Contain("total: 2") + .And.Contain("succeeded: 1") + .And.Contain("failed: 1") + .And.Contain("skipped: 0"); + } + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + } +} diff --git a/test/dotnet-test.Tests/GivenDotnetTestBuildsAndRunsTestsWithDifferentOptions.cs b/test/dotnet-test.Tests/GivenDotnetTestBuildsAndRunsTestsWithDifferentOptions.cs new file mode 100644 index 000000000000..ab4abfd249e5 --- /dev/null +++ b/test/dotnet-test.Tests/GivenDotnetTestBuildsAndRunsTestsWithDifferentOptions.cs @@ -0,0 +1,352 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text.RegularExpressions; +using CommandResult = Microsoft.DotNet.Cli.Utils.CommandResult; + +namespace Microsoft.DotNet.Cli.Test.Tests +{ + public class GivenDotnetTestBuildsAndRunsTestsWithDifferentOptions : SdkTest + { + private const string TestApplicationArgsSeparator = $" {CliConstants.ParametersSeparator} "; + private const string TestApplicationArgsPattern = @".*(Test application arguments).*"; + + public GivenDotnetTestBuildsAndRunsTestsWithDifferentOptions(ITestOutputHelper log) : base(log) + { + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunWithProjectPathWithFailingTests_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MultiTestProjectSolutionWithTests", Guid.NewGuid().ToString()) + .WithSource(); + + string testProjectPath = $"TestProject{Path.DirectorySeparatorChar}TestProject.csproj"; + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .WithTraceOutput() + .Execute(TestingPlatformOptions.ProjectOption.Name, testProjectPath, + TestingPlatformOptions.ConfigurationOption.Name, configuration); + + var testAppArgs = Regex.Matches(result.StdOut!, TestApplicationArgsPattern); + string fullProjectPath = $"{testInstance.TestRoot}{Path.DirectorySeparatorChar}{testProjectPath}"; + Assert.Contains($"{TestingPlatformOptions.ProjectOption.Name} \"{fullProjectPath}\"", testAppArgs.FirstOrDefault()?.Value.Split(TestApplicationArgsSeparator)[0]); + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunWithSolutionPathWithFailingTests_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MultiTestProjectSolutionWithTests", Guid.NewGuid().ToString()) + .WithSource(); + + string testSolutionPath = "MultiTestProjectSolutionWithTests.sln"; + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.SolutionOption.Name, testSolutionPath, + TestingPlatformOptions.ConfigurationOption.Name, configuration); + + Assert.Matches(RegexPatternHelper.GenerateProjectRegexPattern("TestProject", "failed", true), result.StdOut); + Assert.Matches(RegexPatternHelper.GenerateProjectRegexPattern("OtherTestProject", "passed", true), result.StdOut); + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunWithSolutionFilterPathWithFailingTests_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MultiTestProjectSolutionWithTests", Guid.NewGuid().ToString()) + .WithSource(); + + string testSolutionPath = "TestProjects.slnf"; + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.SolutionOption.Name, testSolutionPath, + TestingPlatformOptions.ConfigurationOption.Name, configuration); + + // Assert that only TestProject ran + Assert.Matches(RegexPatternHelper.GenerateProjectRegexPattern("TestProject", "failed", true), result.StdOut); + Assert.DoesNotMatch(RegexPatternHelper.GenerateProjectRegexPattern("OtherTestProject", "passed", true), result.StdOut); + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunWithSolutionFilterPathInOtherDirectory_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MultiTestProjectSolutionWithTests", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory($"{testInstance.Path}{Path.DirectorySeparatorChar}SolutionFilter") + .WithEnableTestingPlatform() + .WithTraceOutput() + .Execute(TestingPlatformOptions.ConfigurationOption.Name, configuration); + + // Assert that only TestProject ran + Assert.Matches(RegexPatternHelper.GenerateProjectRegexPattern("TestProject", "failed", true), result.StdOut); + Assert.DoesNotMatch(RegexPatternHelper.GenerateProjectRegexPattern("OtherTestProject", "passed", true), result.StdOut); + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunWithInvalidProjectExtension_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MultiTestProjectSolutionWithTests", Guid.NewGuid().ToString()) + .WithSource(); + + string invalidProjectPath = $"TestProject{Path.DirectorySeparatorChar}TestProject.txt"; + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ProjectOption.Name, invalidProjectPath, + TestingPlatformOptions.ConfigurationOption.Name, configuration); + + result.StdOut.Should().Contain(string.Format(Tools.Test.LocalizableStrings.CmdInvalidProjectFileExtensionErrorDescription, invalidProjectPath)); + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunWithInvalidSolutionExtension_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MultiTestProjectSolutionWithTests", Guid.NewGuid().ToString()) + .WithSource(); + + string invalidSolutionPath = "TestProjects.txt"; + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.SolutionOption.Name, invalidSolutionPath, + TestingPlatformOptions.ConfigurationOption.Name, configuration); + + result.StdOut.Should().Contain(string.Format(Tools.Test.LocalizableStrings.CmdInvalidSolutionFileExtensionErrorDescription, invalidSolutionPath)); + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunWithBothProjectAndSolutionAndDirectoryOptions_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MultiTestProjectSolutionWithTests", Guid.NewGuid().ToString()) + .WithSource(); + + string testProjectPath = $"TestProject{Path.DirectorySeparatorChar}TestProject.csproj"; + string testSolutionPath = "MultiTestProjectSolutionWithTests.sln"; + string testDirectoryPath = "TestProjects"; + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ProjectOption.Name, testProjectPath, + TestingPlatformOptions.SolutionOption.Name, testSolutionPath, + TestingPlatformOptions.DirectoryOption.Name, testDirectoryPath, + TestingPlatformOptions.ConfigurationOption.Name, configuration); + + result.StdOut.Should().Contain(Tools.Test.LocalizableStrings.CmdMultipleBuildPathOptionsErrorDescription); + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunWithBothProjectAndSolutionOptions_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MultiTestProjectSolutionWithTests", Guid.NewGuid().ToString()) + .WithSource(); + + string testProjectPath = $"TestProject{Path.DirectorySeparatorChar}TestProject.csproj"; + string testSolutionPath = "MultiTestProjectSolutionWithTests.sln"; + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ProjectOption.Name, testProjectPath, + TestingPlatformOptions.SolutionOption.Name, testSolutionPath, + TestingPlatformOptions.ConfigurationOption.Name, configuration); + + result.StdOut.Should().Contain(Tools.Test.LocalizableStrings.CmdMultipleBuildPathOptionsErrorDescription); + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunWithNonExistentProjectPath_ShouldReturnZeroAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MultiTestProjectSolutionWithTests", Guid.NewGuid().ToString()) + .WithSource(); + + string testProjectPath = $"TestProject{Path.DirectorySeparatorChar}OtherTestProject.csproj"; + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.ProjectOption.Name, testProjectPath, + TestingPlatformOptions.ConfigurationOption.Name, configuration); + + string fullProjectPath = $"{testInstance.TestRoot}{Path.DirectorySeparatorChar}{testProjectPath}"; + result.StdOut.Should().Contain(string.Format(Tools.Test.LocalizableStrings.CmdNonExistentFileErrorDescription, fullProjectPath)); + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunWithNonExistentSolutionPath_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MultiTestProjectSolutionWithTests", Guid.NewGuid().ToString()) + .WithSource(); + + string solutionPath = "Solution.sln"; + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.SolutionOption.Name, solutionPath, + TestingPlatformOptions.ConfigurationOption.Name, configuration); + + string fullSolutionPath = $"{testInstance.TestRoot}{Path.DirectorySeparatorChar}{solutionPath}"; + result.StdOut.Should().Contain(string.Format(Tools.Test.LocalizableStrings.CmdNonExistentFileErrorDescription, fullSolutionPath)); + + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunWithNonExistentDirectoryPath_ShouldReturnOneAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("MultiTestProjectSolutionWithTests", Guid.NewGuid().ToString()) + .WithSource(); + + string directoryPath = "Directory"; + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute(TestingPlatformOptions.DirectoryOption.Name, directoryPath, + TestingPlatformOptions.ConfigurationOption.Name, configuration); + + result.StdOut.Should().Contain(string.Format(Tools.Test.LocalizableStrings.CmdNonExistentDirectoryErrorDescription, directoryPath)); + result.ExitCode.Should().Be(ExitCodes.GenericFailure); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunTestProjectSolutionWithConfigurationOption_ShouldReturnZeroAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("TestProjectWithTests", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .WithTraceOutput() + .Execute(TestingPlatformOptions.ConfigurationOption.Name, configuration); + + var testAppArgs = Regex.Matches(result.StdOut!, TestApplicationArgsPattern); + Assert.Contains($"{TestingPlatformOptions.ConfigurationOption.Name} {configuration}", testAppArgs.FirstOrDefault()?.Value.Split(TestApplicationArgsSeparator)[0]); + + result.ExitCode.Should().Be(ExitCodes.Success); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunTestProjectSolutionWithArchOption_ShouldReturnZeroAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("TestProjectWithTests", Guid.NewGuid().ToString()) + .WithSource(); + string arch = "x64"; + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .WithTraceOutput() + .Execute(TestingPlatformOptions.ArchitectureOption.Name, arch, + TestingPlatformOptions.ConfigurationOption.Name, configuration); + + var testAppArgs = Regex.Matches(result.StdOut!, TestApplicationArgsPattern); + Assert.Contains($"{TestingPlatformOptions.ArchitectureOption.Name} {arch}", testAppArgs.FirstOrDefault()?.Value.Split(TestApplicationArgsSeparator)[0]); + + result.ExitCode.Should().Be(ExitCodes.Success); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunSpecificCSProjRunsWithNoBuildAndNoRestoreOptions_ShouldReturnZeroAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("TestProjectWithTests", Guid.NewGuid().ToString()).WithSource(); + + new BuildCommand(testInstance) + .Execute($"/p:Configuration={configuration}") + .Should().Pass(); + + var binDirectory = new FileInfo($"{testInstance.Path}{Path.DirectorySeparatorChar}bin").Directory; + var binDirectoryLastWriteTime = binDirectory?.LastWriteTime; + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .WithTraceOutput() + .Execute(TestingPlatformOptions.ProjectOption.Name, @"TestProject.csproj", + TestingPlatformOptions.ConfigurationOption.Name, configuration); + + // Assert that the bin folder hasn't been modified + Assert.Equal(binDirectoryLastWriteTime, binDirectory?.LastWriteTime); + + var testAppArgs = Regex.Matches(result.StdOut!, TestApplicationArgsPattern); + Assert.Contains($"{TestingPlatformOptions.NoRestoreOption.Name} {TestingPlatformOptions.NoBuildOption.Name}", testAppArgs.FirstOrDefault()?.Value.Split(TestApplicationArgsSeparator)[0]); + + result.ExitCode.Should().Be(ExitCodes.Success); + } + + [InlineData(TestingConstants.Debug)] + [InlineData(TestingConstants.Release)] + [Theory] + public void RunTestProjectSolutionWithBinLogOption_ShouldReturnZeroAsExitCode(string configuration) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("TestProjectWithTests", Guid.NewGuid().ToString()) + .WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .Execute("-bl", TestingPlatformOptions.ConfigurationOption.Name, configuration); + + Assert.True(File.Exists(string.Format("{0}{1}{2}", testInstance.TestRoot, Path.DirectorySeparatorChar, CliConstants.BinLogFileName))); + + result.ExitCode.Should().Be(0); + } + } +} diff --git a/test/dotnet-test.Tests/GivenDotnetTestsRunsWithDifferentCultures.cs b/test/dotnet-test.Tests/GivenDotnetTestsRunsWithDifferentCultures.cs new file mode 100644 index 000000000000..d12ebf18edf1 --- /dev/null +++ b/test/dotnet-test.Tests/GivenDotnetTestsRunsWithDifferentCultures.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using CommandResult = Microsoft.DotNet.Cli.Utils.CommandResult; + +namespace Microsoft.DotNet.Cli.Test.Tests; + +public class GivenDotnetTestsRunsWithDifferentCultures : SdkTest +{ + public GivenDotnetTestsRunsWithDifferentCultures(ITestOutputHelper log) : base(log) + { + } + + [InlineData("en-US")] + [InlineData("de-DE")] + [Theory] + public void CanRunTestsAgainstProjectInLocale(string locale) + { + TestAsset testInstance = _testAssetsManager.CopyTestAsset("TestProjectWithTests", Guid.NewGuid().ToString()).WithSource(); + + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) + .WithWorkingDirectory(testInstance.Path) + .WithEnableTestingPlatform() + .WithCulture(locale) + .Execute(); + + result.ExitCode.Should().Be(0); + } +} diff --git a/test/dotnet-test.Tests/MSBuildHandlerTests.cs b/test/dotnet-test.Tests/MSBuildHandlerTests.cs new file mode 100644 index 000000000000..c5f17d72fcd8 --- /dev/null +++ b/test/dotnet-test.Tests/MSBuildHandlerTests.cs @@ -0,0 +1,111 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.DotNet.Cli.Test.Tests +{ + public class MSBuildHandlerTests + { + [Fact] + public void IsBinaryLoggerEnabled_ShouldReturnTrue_WhenBinaryLoggerArgumentIsPresent() + { + // Arrange + var args = new List { "--binaryLogger" }; + + // Act + var result = MSBuildUtility.IsBinaryLoggerEnabled(args, out string binLogFileName); + + // Assert + Assert.True(result); + Assert.Equal(CliConstants.BinLogFileName, binLogFileName); + } + + [Fact] + public void IsBinaryLoggerEnabled_ShouldReturnTrue_WhenBinaryLoggerArgumentWithFileNameIsPresent() + { + // Arrange + var args = new List { "--binaryLogger:custom.binlog" }; + + // Act + var result = MSBuildUtility.IsBinaryLoggerEnabled(args, out string binLogFileName); + + // Assert + Assert.True(result); + Assert.Equal("custom.binlog", binLogFileName); + } + + [Fact] + public void IsBinaryLoggerEnabled_ShouldReturnFalse_WhenBinaryLoggerArgumentIsNotPresent() + { + // Arrange + var args = new List { "--someOtherArg" }; + + // Act + var result = MSBuildUtility.IsBinaryLoggerEnabled(args, out string binLogFileName); + + // Assert + Assert.False(result); + Assert.Equal(string.Empty, binLogFileName); + } + + [Fact] + public void IsBinaryLoggerEnabled_ShouldRemoveBinaryLoggerArgumentsFromArgs() + { + // Arrange + var args = new List { "--binaryLogger", "--someOtherArg" }; + + // Act + var result = MSBuildUtility.IsBinaryLoggerEnabled(args, out string binLogFileName); + + // Assert + Assert.True(result); + Assert.Equal(CliConstants.BinLogFileName, binLogFileName); + Assert.DoesNotContain("--binaryLogger", args); + } + + [Fact] + public void IsBinaryLoggerEnabled_ShouldHandleMultipleBinaryLoggerArguments() + { + // Arrange + var args = new List { "--binaryLogger", "--binaryLogger:custom1.binlog", "--binaryLogger:custom2.binlog" }; + + // Act + var result = MSBuildUtility.IsBinaryLoggerEnabled(args, out string binLogFileName); + + // Assert + Assert.True(result); + Assert.Equal("custom2.binlog", binLogFileName); + Assert.DoesNotContain("--binaryLogger", args); + Assert.DoesNotContain("--binaryLogger:custom1.binlog", args); + Assert.DoesNotContain("--binaryLogger:custom2.binlog", args); + } + + [Fact] + public void IsBinaryLoggerEnabled_ShouldHandleInvalidBinaryLoggerArgumentFormat() + { + // Arrange + var args = new List { "--binaryLogger:" }; + + // Act + var result = MSBuildUtility.IsBinaryLoggerEnabled(args, out string binLogFileName); + + // Assert + Assert.True(result); + Assert.Equal(CliConstants.BinLogFileName, binLogFileName); + Assert.DoesNotContain("--binaryLogger:", args); + } + + [Fact] + public void IsBinaryLoggerEnabled_ShouldHandleEmptyBinaryLoggerFilename() + { + // Arrange + var args = new List { "--binaryLogger:" }; + + // Act + var result = MSBuildUtility.IsBinaryLoggerEnabled(args, out string binLogFileName); + + // Assert + Assert.True(result); + Assert.Equal(CliConstants.BinLogFileName, binLogFileName); + } + } +} diff --git a/test/dotnet-watch.Tests/Aspire/AspireServiceFactoryTests.cs b/test/dotnet-watch.Tests/Aspire/AspireServiceFactoryTests.cs new file mode 100644 index 000000000000..5e5c721e9f0d --- /dev/null +++ b/test/dotnet-watch.Tests/Aspire/AspireServiceFactoryTests.cs @@ -0,0 +1,150 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Aspire.Tools.Service; + +namespace Microsoft.DotNet.Watch.UnitTests; + +public class AspireServiceFactoryTests +{ + [Fact] + public void GetRunCommandArguments_Empty() + { + var request = new ProjectLaunchRequest() + { + Arguments = null, + DisableLaunchProfile = false, + LaunchProfile = null, + Environment = null, + ProjectPath = "a.csproj" + }; + + var args = AspireServiceFactory.SessionManager.GetRunCommandArguments(request, hostLaunchProfile: null); + + AssertEx.SequenceEqual(["--project", "a.csproj"], args); + } + + [Fact] + public void GetRunCommandArguments_DisableLaunchProfile() + { + var request = new ProjectLaunchRequest() + { + Arguments = null, + DisableLaunchProfile = true, + LaunchProfile = "P", + Environment = [], + ProjectPath = "a.csproj" + }; + + var args = AspireServiceFactory.SessionManager.GetRunCommandArguments(request, hostLaunchProfile: "H"); + + AssertEx.SequenceEqual(["--project", "a.csproj", "--no-launch-profile" ], args); + } + + [Theory] + [InlineData("")] + [InlineData(null)] + public void GetRunCommandArguments_NoLaunchProfile_HostProfile(string? launchProfile) + { + var request = new ProjectLaunchRequest() + { + Arguments = null, + DisableLaunchProfile = false, + LaunchProfile = launchProfile, + Environment = [], + ProjectPath = "a.csproj" + }; + + var args = AspireServiceFactory.SessionManager.GetRunCommandArguments(request, hostLaunchProfile: "H"); + + AssertEx.SequenceEqual(["--project", "a.csproj", "--launch-profile", "H"], args); + } + + [Theory] + [InlineData("")] + [InlineData(null)] + public void GetRunCommandArguments_DisableLaunchProfile_HostProfile(string? launchProfile) + { + var request = new ProjectLaunchRequest() + { + Arguments = null, + DisableLaunchProfile = true, + LaunchProfile = launchProfile, + Environment = [], + ProjectPath = "a.csproj" + }; + + var args = AspireServiceFactory.SessionManager.GetRunCommandArguments(request, hostLaunchProfile: "H"); + + AssertEx.SequenceEqual(["--project", "a.csproj", "--no-launch-profile"], args); + } + + [Theory] + [InlineData("")] + [InlineData(null)] + public void GetRunCommandArguments_NoLaunchProfile_NoHostProfile(string? launchProfile) + { + var request = new ProjectLaunchRequest() + { + Arguments = null, + DisableLaunchProfile = false, + LaunchProfile = launchProfile, + Environment = [], + ProjectPath = "a.csproj" + }; + + var args = AspireServiceFactory.SessionManager.GetRunCommandArguments(request, hostLaunchProfile: null); + + AssertEx.SequenceEqual(["--project", "a.csproj"], args); + } + [Fact] + public void GetRunCommandArguments_LaunchProfile_NoArgs() + { + var request = new ProjectLaunchRequest() + { + Arguments = null, + DisableLaunchProfile = false, + LaunchProfile = "P", + Environment = [], + ProjectPath = "a.csproj" + }; + + var args = AspireServiceFactory.SessionManager.GetRunCommandArguments(request, hostLaunchProfile: "H"); + + AssertEx.SequenceEqual(["--project", "a.csproj", "--launch-profile", "P"], args); + } + + [Fact] + public void GetRunCommandArguments_LaunchProfile_EmptyArgs() + { + var request = new ProjectLaunchRequest() + { + Arguments = [], + DisableLaunchProfile = false, + LaunchProfile = "P", + Environment = [], + ProjectPath = "a.csproj" + }; + + var args = AspireServiceFactory.SessionManager.GetRunCommandArguments(request, hostLaunchProfile: "H"); + + AssertEx.SequenceEqual(["--project", "a.csproj", "--launch-profile", "P", "--no-launch-profile-arguments"], args); + } + + [Fact] + public void GetRunCommandArguments_LaunchProfile_NonEmptyArgs() + { + var request = new ProjectLaunchRequest() + { + Arguments = ["a", "b"], + DisableLaunchProfile = false, + LaunchProfile = "P", + Environment = [], + ProjectPath = "a.csproj" + }; + + var args = AspireServiceFactory.SessionManager.GetRunCommandArguments(request, hostLaunchProfile: "H"); + + AssertEx.SequenceEqual(["--project", "a.csproj", "--launch-profile", "P", "a", "b"], args); + } +} diff --git a/test/dotnet-watch.Tests/Browser/BrowserConnectorTests.cs b/test/dotnet-watch.Tests/Browser/BrowserConnectorTests.cs new file mode 100644 index 000000000000..b6b6c90090be --- /dev/null +++ b/test/dotnet-watch.Tests/Browser/BrowserConnectorTests.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.DotNet.Watch.UnitTests; + +public class BrowserConnectorTests +{ + [Theory] + [InlineData(null, "https://localhost:1234", "https://localhost:1234")] + [InlineData("", "https://localhost:1234", "https://localhost:1234")] + [InlineData(" ", "https://localhost:1234", "https://localhost:1234")] + [InlineData("", "a/b", "a/b")] + [InlineData("x/y", "a/b", "a/b")] + [InlineData("a/b?X=1", "https://localhost:1234", "https://localhost:1234/a/b?X=1")] + [InlineData("https://localhost:1000/a/b", "https://localhost:1234", "https://localhost:1000/a/b")] + [InlineData("https://localhost:1000/x/y?z=u", "https://localhost:1234/a?b=c", "https://localhost:1000/x/y?z=u")] + public void GetLaunchUrl(string? profileLaunchUrl, string outputLaunchUrl, string expected) + { + Assert.Equal(expected, BrowserConnector.GetLaunchUrl(profileLaunchUrl, outputLaunchUrl)); + } +} diff --git a/test/dotnet-watch.Tests/ConsoleReporterTests.cs b/test/dotnet-watch.Tests/ConsoleReporterTests.cs index 0cdb0e91dd7e..f87855e87799 100644 --- a/test/dotnet-watch.Tests/ConsoleReporterTests.cs +++ b/test/dotnet-watch.Tests/ConsoleReporterTests.cs @@ -18,7 +18,6 @@ public void WritesToStandardStreams(bool suppressEmojis) IReporter reporter = new ConsoleReporter(testConsole, verbose: true, quiet: false, suppressEmojis: suppressEmojis); var dotnetWatchDefaultPrefix = $"dotnet watch {(suppressEmojis ? ":" : "⌚")} "; - // stdout reporter.Verbose("verbose {0}"); Assert.Equal($"{dotnetWatchDefaultPrefix}verbose {{0}}" + EOL, testConsole.GetOutput()); testConsole.Clear(); @@ -31,9 +30,8 @@ public void WritesToStandardStreams(bool suppressEmojis) Assert.Equal($"{dotnetWatchDefaultPrefix}warn" + EOL, testConsole.GetOutput()); testConsole.Clear(); - // stderr reporter.Error("error"); - Assert.Equal($"dotnet watch {(suppressEmojis ? ":" : "❌")} error" + EOL, testConsole.GetError()); + Assert.Equal($"dotnet watch {(suppressEmojis ? ":" : "❌")} error" + EOL, testConsole.GetOutput()); testConsole.Clear(); } @@ -46,7 +44,6 @@ public void WritesToStandardStreamsWithCustomEmojis(bool suppressEmojis) IReporter reporter = new ConsoleReporter(testConsole, verbose: true, quiet: false, suppressEmojis: suppressEmojis); var dotnetWatchDefaultPrefix = $"dotnet watch {(suppressEmojis ? ":" : "😄")}"; - // stdout reporter.Verbose("verbose", emoji: "😄"); Assert.Equal($"{dotnetWatchDefaultPrefix} verbose" + EOL, testConsole.GetOutput()); testConsole.Clear(); @@ -59,9 +56,8 @@ public void WritesToStandardStreamsWithCustomEmojis(bool suppressEmojis) Assert.Equal($"{dotnetWatchDefaultPrefix} warn" + EOL, testConsole.GetOutput()); testConsole.Clear(); - // stderr reporter.Error("error", emoji: "😄"); - Assert.Equal($"{dotnetWatchDefaultPrefix} error" + EOL, testConsole.GetError()); + Assert.Equal($"{dotnetWatchDefaultPrefix} error" + EOL, testConsole.GetOutput()); testConsole.Clear(); } diff --git a/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs b/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs index 1ba90a189df1..a4722e75746d 100644 --- a/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs +++ b/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs @@ -90,7 +90,7 @@ public async Task BaselineCompilationError() System.Console.WriteLine(""); """); - await App.AssertOutputLineStartsWith(""); + await App.AssertOutputLineStartsWith("", failure: _ => false); } /// @@ -250,7 +250,7 @@ class AppUpdateHandler await App.AssertOutputLineStartsWith("Updated"); await App.WaitUntilOutputContains( - $"dotnet watch ⚠ [WatchHotReloadApp ({ToolsetInfo.CurrentTargetFramework})] Expected to find a static method 'ClearCache' or 'UpdateApplication' on type 'AppUpdateHandler, WatchHotReloadApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' but neither exists."); + $"dotnet watch ⚠ [WatchHotReloadApp ({ToolsetInfo.CurrentTargetFramework})] Expected to find a static method 'ClearCache', 'UpdateApplication' or 'UpdateContent' on type 'AppUpdateHandler, WatchHotReloadApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' but neither exists."); } [Theory] @@ -289,7 +289,7 @@ class AppUpdateHandler await App.AssertOutputLineStartsWith("Updated"); - await App.WaitUntilOutputContains($"dotnet watch ⚠ [WatchHotReloadApp ({ToolsetInfo.CurrentTargetFramework})] Exception from 'System.Action`1[System.Type[]]': System.InvalidOperationException: Bug!"); + await App.WaitUntilOutputContains($"dotnet watch ⚠ [WatchHotReloadApp ({ToolsetInfo.CurrentTargetFramework})] Exception from 'AppUpdateHandler.ClearCache': System.InvalidOperationException: Bug!"); if (verbose) { @@ -330,7 +330,7 @@ public async Task BlazorWasm(bool projectSpecifiesCapabilities) App.AssertOutputContains(MessageDescriptor.ConfiguredToLaunchBrowser); // Browser is launched based on blazor-devserver output "Now listening on: ...". - await App.WaitUntilOutputContains($"dotnet watch ⌚ Launching browser: http://localhost:{port}/"); + await App.WaitUntilOutputContains($"dotnet watch ⌚ Launching browser: http://localhost:{port}"); // Middleware should have been loaded to blazor-devserver before the browser is launched: App.AssertOutputContains("dbug: Microsoft.AspNetCore.Watch.BrowserRefresh.BlazorWasmHotReloadMiddleware[0]"); @@ -397,7 +397,7 @@ public async Task Razor_Component_ScopedCssAndStaticAssets() App.AssertOutputContains(MessageDescriptor.ConfiguredToUseBrowserRefresh); App.AssertOutputContains(MessageDescriptor.ConfiguredToLaunchBrowser); - App.AssertOutputContains($"dotnet watch ⌚ Launching browser: http://localhost:{port}/"); + App.AssertOutputContains($"dotnet watch ⌚ Launching browser: http://localhost:{port}"); App.Process.ClearOutput(); var scopedCssPath = Path.Combine(testAsset.Path, "RazorClassLibrary", "Components", "Example.razor.css"); @@ -411,11 +411,9 @@ public async Task Razor_Component_ScopedCssAndStaticAssets() UpdateSourceFile(scopedCssPath, newCss); await App.AssertOutputLineStartsWith("dotnet watch 🔥 Hot reload change handled"); - App.AssertOutputContains($"dotnet watch ⌚ Handling file change event for scoped css file {scopedCssPath}."); - App.AssertOutputContains($"dotnet watch ⌚ [RazorClassLibrary ({ToolsetInfo.CurrentTargetFramework})] No refresh server."); - App.AssertOutputContains($"dotnet watch ⌚ [RazorApp ({ToolsetInfo.CurrentTargetFramework})] Refreshing browser."); + App.AssertOutputContains($"dotnet watch ⌚ Sending static asset update request to browser: 'RazorApp.css'."); App.AssertOutputContains($"dotnet watch 🔥 Hot reload of scoped css succeeded."); - App.AssertOutputContains($"dotnet watch ⌚ No C# changes to apply."); + App.AssertOutputContains(MessageDescriptor.NoCSharpChangesToApply); App.Process.ClearOutput(); var cssPath = Path.Combine(testAsset.Path, "RazorApp", "wwwroot", "app.css"); @@ -423,10 +421,9 @@ public async Task Razor_Component_ScopedCssAndStaticAssets() await App.AssertOutputLineStartsWith("dotnet watch 🔥 Hot reload change handled"); - App.AssertOutputContains($"dotnet watch ⌚ Sending static file update request for asset 'app.css'."); - App.AssertOutputContains($"dotnet watch ⌚ [RazorApp ({ToolsetInfo.CurrentTargetFramework})] Refreshing browser."); - App.AssertOutputContains($"dotnet watch 🔥 Hot Reload of static files succeeded."); - App.AssertOutputContains($"dotnet watch ⌚ No C# changes to apply."); + App.AssertOutputContains($"dotnet watch ⌚ Sending static asset update request to browser: 'app.css'."); + App.AssertOutputContains($"dotnet watch 🔥 Hot reload of static files succeeded."); + App.AssertOutputContains(MessageDescriptor.NoCSharpChangesToApply); App.Process.ClearOutput(); } @@ -461,17 +458,17 @@ public async Task MauiBlazor() await App.AssertOutputLineStartsWith("dotnet watch 🔥 Hot reload change handled"); // TODO: Warning is currently reported because UpdateContent is not recognized - // dotnet watch ⚠ [maui-blazor (net9.0-windows10.0.19041.0)] Expected to find a static method 'ClearCache' or 'UpdateApplication' on type 'Microsoft.AspNetCore.Components.WebView.StaticContentHotReloadManager - App.AssertOutputContains("Expected to find a static method"); App.AssertOutputContains("Updates applied: 1 out of 1."); + App.AssertOutputContains("Microsoft.AspNetCore.Components.HotReload.HotReloadManager.UpdateApplication"); + App.Process.ClearOutput(); // update static asset: var cssPath = Path.Combine(testAsset.Path, "wwwroot", "css", "app.css"); UpdateSourceFile(cssPath, content => content.Replace("background-color: white;", "background-color: red;")); - await App.AssertOutputLineStartsWith("dotnet watch 🔥 Hot reload change handled"); - + App.AssertOutputContains("Updates applied: 1 out of 1."); + App.AssertOutputContains("Microsoft.AspNetCore.Components.WebView.StaticContentHotReloadManager.UpdateContent"); App.AssertOutputContains("No C# changes to apply."); } @@ -699,6 +696,8 @@ public async Task Aspire() App.AssertOutputContains("dotnet watch 🔥 Project baselines updated."); App.AssertOutputContains($"dotnet watch ⭐ Starting project: {serviceProjectPath}"); + // Note: sending Ctrl+C via standard input is not the same as sending real Ctrl+C. + // The latter terminates the processes gracefully on Windows, so exit codes -1 are actually not reported. App.SendControlC(); await App.AssertOutputLineStartsWith("dotnet watch 🛑 Shutdown requested. Press Ctrl+C again to force exit."); @@ -713,8 +712,8 @@ public async Task Aspire() { // Unix process may return exit code = 128 + SIGTERM // Exited with error code 143 - await App.AssertOutputLine(line => line.Contains($"[WatchAspire.ApiService ({tfm})] Exited"), failure: _ => false); - await App.AssertOutputLine(line => line.Contains($"[WatchAspire.AppHost ({tfm})] Exited"), failure: _ => false); + await App.AssertOutputLine(line => line.Contains($"[WatchAspire.ApiService ({tfm})] Exited")); + await App.AssertOutputLine(line => line.Contains($"[WatchAspire.AppHost ({tfm})] Exited")); } await App.AssertOutputLineStartsWith("dotnet watch ⭐ Waiting for server to shutdown ..."); diff --git a/test/dotnet-watch.Tests/HotReload/CompilationHandlerTests.cs b/test/dotnet-watch.Tests/HotReload/CompilationHandlerTests.cs index ecefef140e65..9a2429d54f8b 100644 --- a/test/dotnet-watch.Tests/HotReload/CompilationHandlerTests.cs +++ b/test/dotnet-watch.Tests/HotReload/CompilationHandlerTests.cs @@ -18,14 +18,16 @@ public async Task ReferenceOutputAssembly_False() var reporter = new TestReporter(Logger); var options = TestOptions.GetProjectOptions(["--project", hostProject]); + var environmentOptions = TestOptions.GetEnvironmentOptions(Environment.CurrentDirectory, "dotnet"); + var factory = new MSBuildFileSetFactory( rootProjectFile: options.ProjectPath, buildArguments: [], - environmentOptions: new EnvironmentOptions(Environment.CurrentDirectory, "dotnet"), + environmentOptions: environmentOptions, reporter); var projectGraph = factory.TryLoadProjectGraph(projectGraphRequired: false); - var handler = new CompilationHandler(reporter); + var handler = new CompilationHandler(reporter, environmentOptions, CancellationToken.None); await handler.Workspace.UpdateProjectConeAsync(hostProject, CancellationToken.None); diff --git a/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs b/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs index d80f53f48454..518b3464c3e0 100644 --- a/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs +++ b/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs @@ -98,7 +98,10 @@ private RunningWatcher StartWatcher(TestAsset testAsset, string[] args, string w var program = Program.TryCreate( TestOptions.GetCommandLineOptions(["--verbose", ..args, "--project", projectPath]), console, - TestOptions.GetEnvironmentOptions(workingDirectory, TestContext.Current.ToolsetUnderTest.DotNetHostPath, testAsset), + TestOptions.GetEnvironmentOptions(workingDirectory, TestContext.Current.ToolsetUnderTest.DotNetHostPath, testAsset) with + { + ProcessCleanupTimeout = TimeSpan.FromSeconds(0), + }, reporter, out var errorCode); @@ -587,7 +590,7 @@ public async Task IgnoredChange(bool isExisting, bool isIncluded, DirectoryKind var ignoringChangeInHiddenDirectory = w.Reporter.RegisterSemaphore(MessageDescriptor.IgnoringChangeInHiddenDirectory); var ignoringChangeInOutputDirectory = w.Reporter.RegisterSemaphore(MessageDescriptor.IgnoringChangeInOutputDirectory); var fileAdditionTriggeredReEvaluation = w.Reporter.RegisterSemaphore(MessageDescriptor.FileAdditionTriggeredReEvaluation); - var noHotReloadChangesToApply = w.Reporter.RegisterSemaphore(MessageDescriptor.NoHotReloadChangesToApply); + var noHotReloadChangesToApply = w.Reporter.RegisterSemaphore(MessageDescriptor.NoCSharpChangesToApply); Log("Waiting for changes..."); await waitingForChanges.WaitAsync(w.ShutdownSource.Token); diff --git a/test/dotnet-watch.Tests/Internal/EnvironmentVariablesBuilderTest.cs b/test/dotnet-watch.Tests/Internal/EnvironmentVariablesBuilderTest.cs deleted file mode 100644 index 75941f6762a6..000000000000 --- a/test/dotnet-watch.Tests/Internal/EnvironmentVariablesBuilderTest.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace Microsoft.DotNet.Watch.UnitTests -{ - public class EnvironmentVariablesBuilderTest - { - [Fact] - public void Value() - { - var builder = new EnvironmentVariablesBuilder(); - builder.DotNetStartupHookDirective.Add("a"); - builder.AspNetCoreHostingStartupAssembliesVariable.Add("b"); - - var values = new Dictionary(); - builder.AddToEnvironment(values); - AssertEx.SequenceEqual(["[env:DOTNET_STARTUP_HOOKS=a]"], builder.GetCommandLineDirectives()); - AssertEx.SequenceEqual([("ASPNETCORE_HOSTINGSTARTUPASSEMBLIES", "b")], values.Select(e => (e.Key, e.Value))); - } - - [Fact] - public void MultipleValues() - { - var builder = new EnvironmentVariablesBuilder(); - builder.DotNetStartupHookDirective.Add("a1"); - builder.DotNetStartupHookDirective.Add("a2"); - builder.AspNetCoreHostingStartupAssembliesVariable.Add("b1"); - builder.AspNetCoreHostingStartupAssembliesVariable.Add("b2"); - - var values = new Dictionary(); - builder.AddToEnvironment(values); - AssertEx.SequenceEqual([$"[env:DOTNET_STARTUP_HOOKS=a1{Path.PathSeparator}a2]"], builder.GetCommandLineDirectives()); - AssertEx.SequenceEqual([("ASPNETCORE_HOSTINGSTARTUPASSEMBLIES", "b1;b2")], values.Select(e => (e.Key, e.Value))); - } - } -} diff --git a/test/dotnet-watch.Tests/Internal/EnvironmentVariablesBuilderTests.cs b/test/dotnet-watch.Tests/Internal/EnvironmentVariablesBuilderTests.cs new file mode 100644 index 000000000000..509cadb17854 --- /dev/null +++ b/test/dotnet-watch.Tests/Internal/EnvironmentVariablesBuilderTests.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.DotNet.Watch.UnitTests +{ + public class EnvironmentVariablesBuilderTests + { + [Fact] + public void Value() + { + var builder = new EnvironmentVariablesBuilder(); + builder.DotNetStartupHooks.Add("a"); + builder.AspNetCoreHostingStartupAssemblies.Add("b"); + + var env = builder.GetEnvironment(); + AssertEx.SequenceEqual( + [ + ("DOTNET_STARTUP_HOOKS", "a"), + ("ASPNETCORE_HOSTINGSTARTUPASSEMBLIES", "b") + ], env); + } + + [Fact] + public void MultipleValues() + { + var builder = new EnvironmentVariablesBuilder(); + builder.DotNetStartupHooks.Add("a1"); + builder.DotNetStartupHooks.Add("a2"); + builder.AspNetCoreHostingStartupAssemblies.Add("b1"); + builder.AspNetCoreHostingStartupAssemblies.Add("b2"); + + var env = builder.GetEnvironment(); + AssertEx.SequenceEqual( + [ + ("DOTNET_STARTUP_HOOKS", $"a1{Path.PathSeparator}a2"), + ("ASPNETCORE_HOSTINGSTARTUPASSEMBLIES", "b1;b2") + ], env); + } + } +} diff --git a/test/dotnet-watch.Tests/MsBuildFileSetFactoryTest.cs b/test/dotnet-watch.Tests/MsBuildFileSetFactoryTest.cs index d014a3de148f..0a3da79c4ef3 100644 --- a/test/dotnet-watch.Tests/MsBuildFileSetFactoryTest.cs +++ b/test/dotnet-watch.Tests/MsBuildFileSetFactoryTest.cs @@ -323,9 +323,7 @@ public async Task ProjectReferences_Graph() .Path; var projectA = Path.Combine(testDirectory, "A", "A.csproj"); - var options = new EnvironmentOptions( - MuxerPath: MuxerPath, - WorkingDirectory: testDirectory); + var options = TestOptions.GetEnvironmentOptions(workingDirectory: testDirectory, muxerPath: MuxerPath); var output = new List(); _reporter.OnProcessOutput += line => output.Add(line.Content); @@ -384,9 +382,7 @@ public async Task MsbuildOutput() var project1Path = GetTestProjectPath(project1); - var options = new EnvironmentOptions( - MuxerPath: MuxerPath, - WorkingDirectory: Path.GetDirectoryName(project1Path)!); + var options = TestOptions.GetEnvironmentOptions(workingDirectory: Path.GetDirectoryName(project1Path)!, muxerPath: MuxerPath); var output = new List(); _reporter.OnProcessOutput += line => output.Add($"{(line.IsError ? "[stderr]" : "[stdout]")} {line.Content}"); @@ -406,10 +402,7 @@ private Task Evaluate(TestAsset projectPath) private async Task Evaluate(string projectPath) { - var options = new EnvironmentOptions( - MuxerPath: MuxerPath, - WorkingDirectory: Path.GetDirectoryName(projectPath)!); - + var options = TestOptions.GetEnvironmentOptions(workingDirectory: Path.GetDirectoryName(projectPath)!, muxerPath: MuxerPath); var factory = new MSBuildFileSetFactory(projectPath, buildArguments: [], options, _reporter); var result = await factory.TryCreateAsync(requireProjectGraph: null, CancellationToken.None); Assert.NotNull(result); diff --git a/test/dotnet-watch.Tests/Utilities/AssertEx.cs b/test/dotnet-watch.Tests/Utilities/AssertEx.cs index da8237fa2aed..07e37a604de4 100644 --- a/test/dotnet-watch.Tests/Utilities/AssertEx.cs +++ b/test/dotnet-watch.Tests/Utilities/AssertEx.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#nullable disable +#pragma warning disable IDE0240 // nullable is redundant +#nullable enable using System.Collections; +using System.Diagnostics; using Xunit.Sdk; namespace Microsoft.DotNet.Watch.UnitTests @@ -36,7 +38,7 @@ public static bool Equals(T left, T right) return Instance.Equals(left, right); } - bool IEqualityComparer.Equals(T x, T y) + bool IEqualityComparer.Equals(T? x, T? y) { if (CanBeNull()) { @@ -51,7 +53,7 @@ bool IEqualityComparer.Equals(T x, T y) } } - if (x.GetType() != y.GetType()) + if (x!.GetType() != y!.GetType()) { return false; } @@ -105,7 +107,7 @@ int IEqualityComparer.GetHashCode(T obj) } } - public static void Equal(T expected, T actual, IEqualityComparer comparer = null, string message = null) + public static void Equal(T expected, T actual, IEqualityComparer? comparer = null, string? message = null) { if (ReferenceEquals(expected, actual)) { @@ -136,19 +138,19 @@ public static void Equal(T expected, T actual, IEqualityComparer comparer public static void Equal( IEnumerable expected, IEnumerable actual, - IEqualityComparer comparer = null, - string message = null, - string itemSeparator = null, - Func itemInspector = null) + IEqualityComparer? comparer = null, + string? message = null, + string? itemSeparator = null, + Func? itemInspector = null) => SequenceEqual(expected, actual, comparer, message, itemSeparator, itemInspector); public static void SequenceEqual( IEnumerable expected, IEnumerable actual, - IEqualityComparer comparer = null, - string message = null, - string itemSeparator = null, - Func itemInspector = null) + IEqualityComparer? comparer = null, + string? message = null, + string? itemSeparator = null, + Func? itemInspector = null) { if (expected == null) { @@ -159,7 +161,10 @@ public static void SequenceEqual( Assert.NotNull(actual); } - if (!expected.SequenceEqual(actual, comparer ?? EqualityComparer.Default)) + Debug.Assert(expected != null); + Debug.Assert(actual != null); + + if (!expected.SequenceEqual(actual, comparer)) { Fail(GetAssertMessage(expected, actual, message, itemInspector, itemSeparator)); } @@ -168,11 +173,11 @@ public static void SequenceEqual( private static string GetAssertMessage( IEnumerable expected, IEnumerable actual, - string prefix = null, - Func itemInspector = null, - string itemSeparator = null) + string? prefix = null, + Func? itemInspector = null, + string? itemSeparator = null) { - itemInspector ??= (typeof(T) == typeof(byte)) ? b => $"0x{b:X2}" : new Func(obj => (obj != null) ? obj.ToString() : ""); + itemInspector ??= (typeof(T) == typeof(byte)) ? b => $"0x{b:X2}" : new Func(obj => (obj != null) ? obj.ToString() ?? "" : ""); itemSeparator ??= (typeof(T) == typeof(byte)) ? ", " : "," + Environment.NewLine; var expectedString = string.Join(itemSeparator, expected.Take(10).Select(itemInspector)); @@ -199,9 +204,12 @@ private static string GetAssertMessage( return message.ToString(); } - public static void Empty(string actual, string message = null) + public static void Empty(string actual, string? message = null) => Equal("", actual, message: message); + public static void Empty(IEnumerable collection) + => SequenceEqual([], collection); + public static void Fail(string message) => throw new XunitException(message); diff --git a/test/dotnet-watch.Tests/Utilities/MockFileSetFactory.cs b/test/dotnet-watch.Tests/Utilities/MockFileSetFactory.cs index 7f48c87c7b63..2e744aa3c194 100644 --- a/test/dotnet-watch.Tests/Utilities/MockFileSetFactory.cs +++ b/test/dotnet-watch.Tests/Utilities/MockFileSetFactory.cs @@ -8,7 +8,7 @@ namespace Microsoft.DotNet.Watch.UnitTests; internal class MockFileSetFactory() : MSBuildFileSetFactory( rootProjectFile: "test.csproj", buildArguments: [], - new EnvironmentOptions(Environment.CurrentDirectory, "dotnet"), + TestOptions.GetEnvironmentOptions(Environment.CurrentDirectory, "dotnet"), NullReporter.Singleton) { public Func TryCreateImpl; diff --git a/test/dotnet-watch.Tests/Utilities/TestOptions.cs b/test/dotnet-watch.Tests/Utilities/TestOptions.cs index 690f75d3acb7..e18914e56173 100644 --- a/test/dotnet-watch.Tests/Utilities/TestOptions.cs +++ b/test/dotnet-watch.Tests/Utilities/TestOptions.cs @@ -13,7 +13,8 @@ public static int GetTestPort() public static readonly ProjectOptions ProjectOptions = GetProjectOptions([]); public static EnvironmentOptions GetEnvironmentOptions(string workingDirectory = "", string muxerPath = "", TestAsset? asset = null) - => new(workingDirectory, muxerPath, TestFlags: TestFlags.RunningAsTest, TestOutput: asset != null ? GetWatchTestOutputPath(asset) : ""); + // 0 timeout for process cleanup in tests. We can't send Ctrl+C, so process termination must be forced. + => new(workingDirectory, muxerPath, ProcessCleanupTimeout: TimeSpan.FromSeconds(0), TestFlags: TestFlags.RunningAsTest, TestOutput: asset != null ? GetWatchTestOutputPath(asset) : ""); public static CommandLineOptions GetCommandLineOptions(string[] args) => CommandLineOptions.Parse(args, NullReporter.Singleton, TextWriter.Null, out _) ?? throw new InvalidOperationException(); diff --git a/test/dotnet-watch.Tests/Utilities/TestRuntimeProcessLauncher.cs b/test/dotnet-watch.Tests/Utilities/TestRuntimeProcessLauncher.cs index a3dea75eaf4b..f8f130cf2a7f 100644 --- a/test/dotnet-watch.Tests/Utilities/TestRuntimeProcessLauncher.cs +++ b/test/dotnet-watch.Tests/Utilities/TestRuntimeProcessLauncher.cs @@ -9,7 +9,7 @@ internal class TestRuntimeProcessLauncher(ProjectLauncher projectLauncher) : IRu { public class Factory(Action? initialize = null) : IRuntimeProcessLauncherFactory { - public IRuntimeProcessLauncher TryCreate(ProjectGraphNode projectNode, ProjectLauncher projectLauncher, IReadOnlyList buildArguments) + public IRuntimeProcessLauncher TryCreate(ProjectGraphNode projectNode, ProjectLauncher projectLauncher, ProjectOptions hostProjectOptions) { var service = new TestRuntimeProcessLauncher(projectLauncher); initialize?.Invoke(service); diff --git a/test/dotnet-watch.Tests/Watch/BrowserLaunchTests.cs b/test/dotnet-watch.Tests/Watch/BrowserLaunchTests.cs index fc55382456ac..569c2b8d07ac 100644 --- a/test/dotnet-watch.Tests/Watch/BrowserLaunchTests.cs +++ b/test/dotnet-watch.Tests/Watch/BrowserLaunchTests.cs @@ -27,7 +27,7 @@ public async Task LaunchesBrowserOnStart() Assert.Contains(App.Process.Output, line => line.Contains("Hosting environment: Development")); // Verify we launched the browser. - Assert.Contains(App.Process.Output, line => line.Contains("dotnet watch ⌚ Launching browser: https://localhost:5001/")); + Assert.Contains(App.Process.Output, line => line.Contains("dotnet watch ⌚ Launching browser: https://localhost:5001")); } [Fact] @@ -43,7 +43,7 @@ public async Task UsesBrowserSpecifiedInEnvironment() await App.AssertOutputLineStartsWith(MessageDescriptor.ConfiguredToLaunchBrowser); // Verify we launched the browser. - await App.AssertOutputLineStartsWith("dotnet watch ⌚ Launching browser: mycustombrowser.bat https://localhost:5001/"); + await App.AssertOutputLineStartsWith("dotnet watch ⌚ Launching browser: mycustombrowser.bat https://localhost:5001"); } } } diff --git a/test/dotnet-watch.Tests/Watch/Utilities/WatchableApp.cs b/test/dotnet-watch.Tests/Watch/Utilities/WatchableApp.cs index b8321d2739ff..df0e4a8f435e 100644 --- a/test/dotnet-watch.Tests/Watch/Utilities/WatchableApp.cs +++ b/test/dotnet-watch.Tests/Watch/Utilities/WatchableApp.cs @@ -77,10 +77,8 @@ public async Task AssertOutputLineStartsWith(string expectedPrefix, Pred return line.Substring(expectedPrefix.Length); } - public Task AssertOutputLine(Predicate predicate, Predicate failure = null) - => Process.GetOutputLineAsync( - success: predicate, - failure: failure ?? new Predicate(line => line.Contains(WatchErrorOutputEmoji, StringComparison.Ordinal))); + public Task AssertOutputLine(Predicate predicate) + => Process.GetOutputLineAsync(success: predicate, failure: _ => false); public async Task AssertOutputLineEquals(string expectedLine) => Assert.Equal("", await AssertOutputLineStartsWith(expectedLine)); @@ -127,11 +125,14 @@ public void Start(TestAsset asset, IEnumerable arguments, string relativ commandSpec.WithEnvironmentVariable("__DOTNET_WATCH_TEST_OUTPUT_DIR", testOutputPath); commandSpec.WithEnvironmentVariable("Microsoft_CodeAnalysis_EditAndContinue_LogDir", testOutputPath); - // suppress all DCP timeouts: + // suppress all timeouts: commandSpec.WithEnvironmentVariable("DCP_IDE_REQUEST_TIMEOUT_SECONDS", "100000"); commandSpec.WithEnvironmentVariable("DCP_IDE_NOTIFICATION_TIMEOUT_SECONDS", "100000"); commandSpec.WithEnvironmentVariable("DCP_IDE_NOTIFICATION_KEEPALIVE_SECONDS", "100000"); + // 0 timeout for process cleanup in tests. We can't send Ctrl+C, so process termination must be forced. + commandSpec.WithEnvironmentVariable("DOTNET_WATCH_PROCESS_CLEANUP_TIMEOUT_MS", "0"); + foreach (var env in EnvironmentVariables) { commandSpec.WithEnvironmentVariable(env.Key, env.Value); diff --git a/test/dotnet-workload-install.Tests/MockNuGetPackageInstaller.cs b/test/dotnet-workload-install.Tests/MockNuGetPackageInstaller.cs index 8411c95f777f..ce67bb4d6cc6 100644 --- a/test/dotnet-workload-install.Tests/MockNuGetPackageInstaller.cs +++ b/test/dotnet-workload-install.Tests/MockNuGetPackageInstaller.cs @@ -15,6 +15,7 @@ internal class MockNuGetPackageDownloader : INuGetPackageDownloader private readonly string _downloadPath; private readonly bool _manifestDownload; private NuGetVersion _lastPackageVersion = new("1.0.0"); + private IEnumerable _packageVersions; public List<(PackageId id, NuGetVersion version, DirectoryPath? downloadFolder, PackageSourceLocation packageSourceLocation)> DownloadCallParams = new(); @@ -24,7 +25,7 @@ internal class MockNuGetPackageDownloader : INuGetPackageDownloader public HashSet PackageIdsToNotFind { get; set; } = new HashSet(StringComparer.OrdinalIgnoreCase); - public MockNuGetPackageDownloader(string dotnetRoot = null, bool manifestDownload = false) + public MockNuGetPackageDownloader(string dotnetRoot = null, bool manifestDownload = false, IEnumerable packageVersions = null) { _manifestDownload = manifestDownload; _downloadPath = dotnetRoot == null ? string.Empty : Path.Combine(dotnetRoot, "metadata", "temp"); @@ -32,6 +33,8 @@ public MockNuGetPackageDownloader(string dotnetRoot = null, bool manifestDownloa { Directory.CreateDirectory(_downloadPath); } + + _packageVersions = packageVersions; } public Task DownloadPackageAsync(PackageId packageId, @@ -81,7 +84,7 @@ public Task> ExtractPackageAsync(string packagePath, Directo return Task.FromResult(new List() as IEnumerable); } - public Task> GetLatestPackageVersions(PackageId packageId, int numberOfResults, PackageSourceLocation packageSourceLocation = null, bool includePreview = false) => Task.FromResult(Enumerable.Empty()); + public Task> GetLatestPackageVersions(PackageId packageId, int numberOfResults, PackageSourceLocation packageSourceLocation = null, bool includePreview = false) => Task.FromResult(_packageVersions ?? Enumerable.Empty()); public Task GetLatestPackageVersion(PackageId packageId, PackageSourceLocation packageSourceLocation = null, bool includePreview = false) { diff --git a/test/dotnet-workload-install.Tests/MockPackWorkloadInstaller.cs b/test/dotnet-workload-install.Tests/MockPackWorkloadInstaller.cs index cd7be5779eb4..22bc239f47e7 100644 --- a/test/dotnet-workload-install.Tests/MockPackWorkloadInstaller.cs +++ b/test/dotnet-workload-install.Tests/MockPackWorkloadInstaller.cs @@ -28,9 +28,10 @@ internal class MockPackWorkloadInstaller : IInstaller public MockInstallationRecordRepository InstallationRecordRepository; public bool FailingRollback; public bool FailingGarbageCollection; + public WorkloadSet InstalledWorkloadSet; private readonly string FailingPack; private readonly string _dotnetDir; - private string workloadSetContents; + private Dictionary workloadSetContents; List HistoryRecords = new(); public IWorkloadResolver WorkloadResolver { get; set; } @@ -38,7 +39,7 @@ internal class MockPackWorkloadInstaller : IInstaller public int ExitCode => 0; public MockPackWorkloadInstaller(string dotnetDir = null, string failingWorkload = null, string failingPack = null, bool failingRollback = false, IList installedWorkloads = null, - IList installedPacks = null, bool failingGarbageCollection = false, List records = null, string workloadSetContents = "") + IList installedPacks = null, bool failingGarbageCollection = false, List records = null, Dictionary workloadSetContents = null) { InstallationRecordRepository = new MockInstallationRecordRepository(failingWorkload, installedWorkloads?.ToHashSet()); FailingRollback = failingRollback; @@ -67,9 +68,7 @@ IEnumerable GetPacksForWorkloads(IEnumerable workloadIds) } public void UpdateInstallMode(SdkFeatureBand sdkFeatureBand, bool? newMode) - { - throw new NotImplementedException(); - } + { } public void AdjustWorkloadSetInInstallState(SdkFeatureBand sdkFeatureBand, string workloadVersion) { @@ -121,14 +120,14 @@ public void InstallWorkloads(IEnumerable workloadIds, SdkFeatureBand }); } - public WorkloadSet GetWorkloadSetContents(string workloadSetVersion) => WorkloadSet.FromJson(workloadSetContents, new SdkFeatureBand("6.0.100")); + public WorkloadSet GetWorkloadSetContents(string workloadSetVersion) => WorkloadSet.FromJson(workloadSetContents[workloadSetVersion], new SdkFeatureBand("6.0.100")); public WorkloadSet InstallWorkloadSet(ITransactionContext context, string workloadSetVersion, DirectoryPath? offlineCache = null) { InstallWorkloadSetCalled = true; - var workloadSet = WorkloadSet.FromJson(workloadSetContents, new SdkFeatureBand("6.0.100")); - workloadSet.Version = workloadSetVersion; - return workloadSet; + InstalledWorkloadSet = WorkloadSet.FromJson(workloadSetContents[workloadSetVersion], new SdkFeatureBand("6.0.100")); + InstalledWorkloadSet.Version = workloadSetVersion; + return InstalledWorkloadSet; } public void WriteWorkloadHistoryRecord(WorkloadHistoryRecord workloadHistoryRecord, string sdkFeatureBand) diff --git a/test/dotnet-workload-search.Tests/GivenDotnetWorkloadSearch.cs b/test/dotnet-workload-search.Tests/GivenDotnetWorkloadSearch.cs index 1fa0266c2cd8..33701a83bf08 100644 --- a/test/dotnet-workload-search.Tests/GivenDotnetWorkloadSearch.cs +++ b/test/dotnet-workload-search.Tests/GivenDotnetWorkloadSearch.cs @@ -3,9 +3,13 @@ #nullable disable +using Microsoft.Deployment.DotNet.Releases; +using Microsoft.DotNet.Cli.NuGetPackageDownloader; using Microsoft.DotNet.Cli.Workload.Install.Tests; using Microsoft.DotNet.Workloads.Workload.Search; using Microsoft.NET.Sdk.WorkloadManifestReader; +using Microsoft.TemplateEngine.Abstractions.Components; +using NuGet.Versioning; namespace Microsoft.DotNet.Cli.Workload.Search.Tests { @@ -59,6 +63,54 @@ public void GivenNoWorkloadsAreInstalledSearchIsEmpty() _reporter.Lines.Count.Should().Be(4, because: "Output should have header and no values."); } + [Fact] + public void GivenWorkloadSearchWithComponentsItFindsHighestMatchingSet() + { + string workloadSet1 = @"{ +""Microsoft.NET.Sdk.Android"": ""17.5.9/9.0.100"", +""Microsoft.NET.Sdk.macOS"": ""14.5.92/9.0.100"" +} +"; + string workloadSet2 = @"{ +""Microsoft.NET.Sdk.Android"": ""17.5.9/9.0.100"", +""Microsoft.NET.Sdk.macOS"": ""14.5.92/9.0.100"" +} +"; + string workloadSet3 = @"{ +""Microsoft.NET.Sdk.Android"": ""17.5.9/9.0.100"", +""Microsoft.NET.Sdk.Maui"": ""14.5.92/9.0.100"" +} +"; + string workloadSet4 = @"{ +""Microsoft.NET.Sdk.Android"": ""17.5.9/9.0.100"", +""Microsoft.NET.Sdk.macOS"": ""14.5.93/9.0.100"" +} +"; + Dictionary workloadSets = new() + { + { "9.0.100", workloadSet1 }, + { "9.0.101", workloadSet2 }, + { "9.0.102", workloadSet3 }, + { "9.0.103", workloadSet4 } + }; + + MockPackWorkloadInstaller installer = new(workloadSetContents: workloadSets); + MockNuGetPackageDownloader nugetPackageDownloader = new(packageVersions: [new NuGetVersion("9.103.0"), new NuGetVersion("9.102.0"), new NuGetVersion("9.101.0"), new NuGetVersion("9.100.0")]); + var parseResult = Parser.Instance.Parse("dotnet workload search version android@17.5.9 macos@14.5.92 --take 1"); + MockWorkloadResolver resolver = new( + [new WorkloadResolver.WorkloadInfo(new WorkloadId("Microsoft.NET.Sdk.Android"), null), + new WorkloadResolver.WorkloadInfo(new WorkloadId("Microsoft.NET.Sdk.macOS"), null), + new WorkloadResolver.WorkloadInfo(new WorkloadId("Microsoft.NET.Sdk.Maui"), null)], + getManifest: id => id.Equals(new WorkloadId("android")) ? WorkloadManifest.CreateForTests("Microsoft.NET.Sdk.Android") : + id.Equals(new WorkloadId("macos")) ? WorkloadManifest.CreateForTests("Microsoft.NET.Sdk.macOS") : + WorkloadManifest.CreateForTests("Microsoft.NET.Sdk.Maui")); + var command = new WorkloadSearchVersionsCommand(parseResult, _reporter, installer: installer, nugetPackageDownloader: nugetPackageDownloader, resolver: resolver, sdkVersion: new ReleaseVersion(9, 0, 100)); + _reporter.Clear(); + command.Execute(); + _reporter.Lines.Count.Should().Be(1); + _reporter.Lines.Single().Should().Be("9.0.101"); + } + [Fact] public void GivenNoStubIsProvidedSearchShowsAllWorkloads() { diff --git a/test/dotnet-workload-search.Tests/MockWorkloadResolver.cs b/test/dotnet-workload-search.Tests/MockWorkloadResolver.cs index 42fdfc9715c5..ca5c48b55f71 100644 --- a/test/dotnet-workload-search.Tests/MockWorkloadResolver.cs +++ b/test/dotnet-workload-search.Tests/MockWorkloadResolver.cs @@ -13,17 +13,20 @@ public class MockWorkloadResolver : IWorkloadResolver private readonly IEnumerable _installedManifests; private readonly Func> _getPacksInWorkload; private readonly Func _getPackInfo; + private readonly Func _getManifest; public MockWorkloadResolver( IEnumerable availableWorkloads, IEnumerable installedManifests = null, Func> getPacks = null, - Func getPackInfo = null) + Func getPackInfo = null, + Func getManifest = null) { _availableWorkloads = availableWorkloads; _installedManifests = installedManifests; _getPacksInWorkload = getPacks; _getPackInfo = getPackInfo; + _getManifest = getManifest; } public IEnumerable GetAvailableWorkloads() => _availableWorkloads; @@ -44,7 +47,7 @@ public void RefreshWorkloadManifests() { /* noop */ } public IWorkloadManifestProvider.WorkloadVersionInfo GetWorkloadVersion() => new IWorkloadManifestProvider.WorkloadVersionInfo("8.0.100.2"); public IEnumerable GetUpdatedWorkloads(WorkloadResolver advertisingManifestResolver, IEnumerable installedWorkloads) => throw new NotImplementedException(); WorkloadResolver IWorkloadResolver.CreateOverlayResolver(IWorkloadManifestProvider overlayManifestProvider) => throw new NotImplementedException(); - WorkloadManifest IWorkloadResolver.GetManifestFromWorkload(WorkloadId workloadId) => throw new NotImplementedException(); + WorkloadManifest IWorkloadResolver.GetManifestFromWorkload(WorkloadId workloadId) => _getManifest?.Invoke(workloadId) ?? throw new NotImplementedException(); public IWorkloadManifestProvider GetWorkloadManifestProvider() => throw new NotImplementedException(); } } diff --git a/test/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs b/test/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs index 92733f5c45f4..690ccdd02e7e 100644 --- a/test/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs +++ b/test/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs @@ -17,6 +17,8 @@ using System.Text.Json; using Microsoft.DotNet.Cli.Workload.Search.Tests; using Microsoft.DotNet.Workloads.Workload.History; +using Microsoft.VisualStudio.TestPlatform.ObjectModel; +using NuGet.Versioning; namespace Microsoft.DotNet.Cli.Workload.Update.Tests { @@ -303,19 +305,19 @@ public void UpdateViaWorkloadSet(bool upgrade) } "; var nugetPackageDownloader = new MockNuGetPackageDownloader(); - var workloadResolver = new MockWorkloadResolver(new WorkloadInfo[] { new WorkloadInfo(new WorkloadId("android"), string.Empty) }, getPacks: id => Enumerable.Empty(), installedManifests: Enumerable.Empty()); + var workloadResolver = new MockWorkloadResolver([new WorkloadInfo(new WorkloadId("android"), string.Empty)], getPacks: id => [], installedManifests: []); var workloadInstaller = new MockPackWorkloadInstaller( dotnetDir, - installedWorkloads: new List() { new WorkloadId("android")}, - workloadSetContents: workloadSetContents) + installedWorkloads: [new WorkloadId("android")], + workloadSetContents: new Dictionary() { { "8.0.302", workloadSetContents } }) { WorkloadResolver = workloadResolver }; var oldVersion = upgrade ? "2.3.2" : "2.3.6"; var workloadManifestUpdater = new MockWorkloadManifestUpdater( - manifestUpdates: new ManifestUpdateWithWorkloads[] { + manifestUpdates: [ new ManifestUpdateWithWorkloads(new ManifestVersionUpdate(new ManifestId("android"), new ManifestVersion("2.3.4"), "8.0.200"), Enumerable.Empty>().ToDictionary()) - }, + ], fromWorkloadSet: true, workloadSetVersion: workloadSetVersion); var resolverFactory = new MockWorkloadResolverFactory(dotnetDir, sdkVersion, workloadResolver, userProfileDir); var updateCommand = new WorkloadUpdateCommand(Parser.Instance.Parse("dotnet workload update"), Reporter.Output, resolverFactory, workloadInstaller, nugetPackageDownloader, workloadManifestUpdater); @@ -332,6 +334,64 @@ public void UpdateViaWorkloadSet(bool upgrade) workloadInstaller.InstalledManifests[0].manifestUpdate.NewVersion.ToString().Should().Be("2.3.4"); } + [Fact] + public void GivenWorkloadUpdateItFindsGreatestWorkloadSetWithSpecifiedComponents() + { + string workloadSet1 = @"{ +""Microsoft.NET.Sdk.iOS"": ""17.5.9/9.0.100"", +""Microsoft.NET.Sdk.macOS"": ""14.5.92/9.0.100"" +} +"; + string workloadSet2 = @"{ +""Microsoft.NET.Sdk.iOS"": ""17.5.9/9.0.100"", +""Microsoft.NET.Sdk.macOS"": ""14.5.92/9.0.100"" +} +"; + string workloadSet3 = @"{ +""Microsoft.NET.Sdk.iOS"": ""17.5.9/9.0.100"", +""Microsoft.NET.Sdk.Maui"": ""14.5.92/9.0.100"" +} +"; + string workloadSet4 = @"{ +""Microsoft.NET.Sdk.iOS"": ""17.5.9/9.0.100"", +""Microsoft.NET.Sdk.macOS"": ""14.5.93/9.0.100"" +} +"; + Dictionary workloadSets = new() + { + { "9.0.100", workloadSet1 }, + { "9.0.101", workloadSet2 }, + { "9.0.102", workloadSet3 }, + { "9.0.103", workloadSet4 } + }; + + var parseResult = Parser.Instance.Parse("dotnet workload update --version ios@17.5.9 macos@14.5.92"); + MockPackWorkloadInstaller installer = new(workloadSetContents: workloadSets); + var testDirectory = _testAssetsManager.CreateTestDirectory(testName: "GivenWorkloadUpdateItFindsGreatestWorkloadSetWithSpecifiedComponents").Path; + WorkloadManifest iosManifest = WorkloadManifest.CreateForTests("Microsoft.NET.Sdk.iOS"); + WorkloadManifest macosManifest = WorkloadManifest.CreateForTests("Microsoft.NET.Sdk.macOS"); + WorkloadManifest mauiManifest = WorkloadManifest.CreateForTests("Microsoft.NET.Sdk.Maui"); + MockWorkloadResolver resolver = new([new WorkloadInfo(new WorkloadId("ios"), ""), new WorkloadInfo(new WorkloadId("macos"), ""), new WorkloadInfo(new WorkloadId("maui"), "")], + installedManifests: [ + new WorkloadManifestInfo("Microsoft.NET.Sdk.iOS", "17.4.3", Path.Combine(testDirectory, "iosManifest"), "9.0.100"), + new WorkloadManifestInfo("Microsoft.NET.Sdk.macOS", "14.4.3", Path.Combine(testDirectory, "macosManifest"), "9.0.100"), + new WorkloadManifestInfo("Microsoft.NET.Sdk.Maui", "14.4.3", Path.Combine(testDirectory, "mauiManifest"), "9.0.100") + ], + getManifest: id => id.ToString().Equals("ios") ? iosManifest : id.ToString().Equals("macos") ? macosManifest : mauiManifest); + MockNuGetPackageDownloader nugetPackageDownloader = new(packageVersions: [new NuGetVersion("9.103.0"), new NuGetVersion("9.102.0"), new NuGetVersion("9.101.0"), new NuGetVersion("9.100.0")]); + WorkloadUpdateCommand command = new( + parseResult, + reporter: null, + workloadResolverFactory: new MockWorkloadResolverFactory(Path.Combine(testDirectory, "dotnet"), "9.0.100", resolver, userProfileDir: testDirectory), + workloadInstaller: installer, + nugetPackageDownloader: nugetPackageDownloader, + workloadManifestUpdater: new MockWorkloadManifestUpdater() + ); + command.Execute(); + + installer.InstalledWorkloadSet.Version.Should().Be("9.0.101"); + } + [Fact] public void GivenWorkloadUpdateItRollsBackOnFailedUpdate() { diff --git a/test/dotnet.Tests/GivenThatDotNetRunsCommands.cs b/test/dotnet.Tests/GivenThatDotNetRunsCommands.cs index 1e3c791c158e..7d6fe7820fa4 100644 --- a/test/dotnet.Tests/GivenThatDotNetRunsCommands.cs +++ b/test/dotnet.Tests/GivenThatDotNetRunsCommands.cs @@ -3,6 +3,7 @@ #nullable disable +using System.Runtime.InteropServices; using Microsoft.DotNet.Configurer; using LocalizableStrings = Microsoft.DotNet.Cli.Utils.LocalizableStrings; @@ -39,7 +40,7 @@ public void UnresolvedPlatformReferencesFailAsExpected() public void GivenAMissingHomeVariableItExecutesHelpCommandSuccessfully(string value) { new DotnetCommand(Log) - .WithEnvironmentVariable(CliFolderPathCalculator.PlatformHomeVariableName, value) + .WithEnvironmentVariable(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "USERPROFILE" : "HOME", value) .WithEnvironmentVariable(CliFolderPathCalculator.DotnetHomeVariableName, "") .Execute("--help") .Should() diff --git a/test/dotnet.Tests/GivenThatTheUserIsRunningDotNetForTheFirstTime.cs b/test/dotnet.Tests/GivenThatTheUserIsRunningDotNetForTheFirstTime.cs index 21175ab5bad6..143d0362eb99 100644 --- a/test/dotnet.Tests/GivenThatTheUserIsRunningDotNetForTheFirstTime.cs +++ b/test/dotnet.Tests/GivenThatTheUserIsRunningDotNetForTheFirstTime.cs @@ -27,14 +27,12 @@ public TestCommand Setup(ITestOutputHelper log, TestAssetsManager testAssets, [C var command = new DotnetCommand(log) .WithWorkingDirectory(TestDirectory) - .WithEnvironmentVariable("HOME", testNuGetHome) - .WithEnvironmentVariable("USERPROFILE", testNuGetHome) .WithEnvironmentVariable("APPDATA", testNuGetHome) .WithEnvironmentVariable("DOTNET_CLI_TEST_FALLBACKFOLDER", cliTestFallbackFolder) .WithEnvironmentVariable("DOTNET_CLI_TEST_LINUX_PROFILED_PATH", profiled) .WithEnvironmentVariable("DOTNET_CLI_TEST_OSX_PATHSD_PATH", pathsd) .WithEnvironmentVariable("SkipInvalidConfigurations", "true") - .WithEnvironmentVariable(CliFolderPathCalculator.DotnetHomeVariableName, ""); + .WithEnvironmentVariable(CliFolderPathCalculator.DotnetHomeVariableName, testNuGetHome); NugetFallbackFolder = new DirectoryInfo(cliTestFallbackFolder); DotDotnetFolder = new DirectoryInfo(Path.Combine(testNuGetHome, ".dotnet")); diff --git a/test/dotnet.Tests/ParserTests/CommonOptionsTests.cs b/test/dotnet.Tests/ParserTests/CommonOptionsTests.cs new file mode 100644 index 000000000000..eff7a49b0bf4 --- /dev/null +++ b/test/dotnet.Tests/ParserTests/CommonOptionsTests.cs @@ -0,0 +1,121 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.CommandLine; +using Microsoft.DotNet.Cli; +using Microsoft.DotNet.Tools; + +namespace Microsoft.DotNet.Tests.ParserTests; + +public class CommonOptionsTests +{ + [Fact] + public void Duplicates() + { + var command = new CliRootCommand(); + command.Options.Add(CommonOptions.EnvOption); + + var result = command.Parse(["-e", "A=1", "-e", "A=2"]); + + result.GetValue(CommonOptions.EnvOption) + .Should() + .BeEquivalentTo(new Dictionary { ["A"] = "2" }); + + result.Errors.Should().BeEmpty(); + } + + [Fact] + public void Duplicates_CasingDifference() + { + var command = new CliRootCommand(); + command.Options.Add(CommonOptions.EnvOption); + + var result = command.Parse(["-e", "A=1", "-e", "a=2"]); + + var expected = new Dictionary(); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + expected.Add("A", "2"); + } + else + { + expected.Add("A", "1"); + expected.Add("a", "2"); + } + + result.GetValue(CommonOptions.EnvOption) + .Should() + .BeEquivalentTo(expected); + + result.Errors.Should().BeEmpty(); + } + + [Fact] + public void MultiplePerToken() + { + var command = new CliRootCommand(); + command.Options.Add(CommonOptions.EnvOption); + + var result = command.Parse(["-e", "A=1;B=2,C=3 D=4", "-e", "B==Y=", "-e", "C;=;"]); + + result.GetValue(CommonOptions.EnvOption) + .Should() + .BeEquivalentTo(new Dictionary + { + ["A"] = "1;B=2,C=3 D=4", + ["B"] = "=Y=", + ["C;"] = ";" + }); + + result.Errors.Should().BeEmpty(); + } + + [Fact] + public void NoValue() + { + var command = new CliRootCommand(); + command.Options.Add(CommonOptions.EnvOption); + + var result = command.Parse(["-e", "A"]); + + result.GetValue(CommonOptions.EnvOption) + .Should() + .BeEquivalentTo(new Dictionary { ["A"] = "" }); + + result.Errors.Should().BeEmpty(); + } + + [Fact] + public void WhitespaceTrimming() + { + var command = new CliRootCommand(); + command.Options.Add(CommonOptions.EnvOption); + + var result = command.Parse(["-e", " A \t\n\r\u2002 = X Y \t\n\r\u2002"]); + + result.GetValue(CommonOptions.EnvOption) + .Should() + .BeEquivalentTo(new Dictionary { ["A"] = " X Y \t\n\r\u2002" }); + + result.Errors.Should().BeEmpty(); + } + + [Theory] + [InlineData("")] + [InlineData("=")] + [InlineData("= X")] + [InlineData(" \u2002 = X")] + public void Errors(string token) + { + var command = new CliRootCommand(); + command.Options.Add(CommonOptions.EnvOption); + + var result = command.Parse(["-e", token]); + + result.Errors.Select(e => e.Message).Should().BeEquivalentTo( + [ + string.Format(CommonLocalizableStrings.IncorrectlyFormattedEnvironmentVariables, $"'{token}'") + ]); + } +} diff --git a/test/dotnet.Tests/TestCommandExtensions.cs b/test/dotnet.Tests/TestCommandExtensions.cs index e15968ebf551..952fb1bfb633 100644 --- a/test/dotnet.Tests/TestCommandExtensions.cs +++ b/test/dotnet.Tests/TestCommandExtensions.cs @@ -7,15 +7,7 @@ public static class TestCommandExtensions { public static TestCommand WithUserProfileRoot(this TestCommand testCommand, string path) { - var userProfileEnvironmentVariableName = GetUserProfileEnvironmentVariableName(); - return testCommand.WithEnvironmentVariable(userProfileEnvironmentVariableName, path); - } - - private static string GetUserProfileEnvironmentVariableName() - { - return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) - ? "LocalAppData" - : "HOME"; + return testCommand.WithEnvironmentVariable("DOTNET_CLI_HOME", path); } } } diff --git a/test/dotnet.Tests/dotnet.Tests.csproj b/test/dotnet.Tests/dotnet.Tests.csproj index 4bb8bfdc1df5..e974b3aee799 100644 --- a/test/dotnet.Tests/dotnet.Tests.csproj +++ b/test/dotnet.Tests/dotnet.Tests.csproj @@ -56,6 +56,8 @@ + + PreserveNewest @@ -110,7 +112,6 @@ -