Skip to content

Conversation

@dsplaisted
Copy link
Member

We're not planning to merge this to main yet, but we want to start reviewing the code.

Context: dotnet/designs#339

dsplaisted and others added 30 commits August 14, 2025 22:57
Copilot prompt:

Implement the GetConfiguredInstallType method in #file:'DotnetInstaler.cs' .

This method should look in the PATH and resolve "dotnet" or "dotnet.exe", depending on the current OS.  If it is not found, the return value should be SdkInstallType.None.  If it is found in Program Files, the install type should be SdkInstallType.Admin.  If it is found in another folder, the install type should be SdkInsntallType.User.

However, the method should also check the value of DOTNET_ROOT environment variable.  For a user install, DOTNET_ROOT should be set to the folder where the dotnet executable is found.  For an admin install, DOTNET_ROOT should not be set, but if it is set to the install path under program files, that is OK.  If the DOTNET_ROOT value doesn't match the install location, the method should return SdkInstallType.Inconsistent.
Copilot prompt:

In #method:'Microsoft.DotNet.Tools.Bootstrapper.DotnetInstaler.GetConfiguredInstallType':301-2793 ,  use #method:'Microsoft.DotNet.Cli.Utils.EnvironmentProvider.GetCommandPath':2399-2843 to search for dotnet on the path.
Copilot prompts:

Create a class to represent the contents of a global.json file, and create a corresponding JsonSerializerContext type.

Can you refer to https://learn.microsoft.com/en-us/dotnet/core/tools/global-json to update the schema you are using for the global.json file?  AllowPrerelease should be a booleann, and instead of Path there should be a Paths property which is an array of strings.
Copilot prompts:

Implement #method:'Microsoft.DotNet.Tools.Bootstrapper.DotnetInstaller.GetDefaultDotnetInstallPath':2814-2986 .  It look for a global.json file starting in the specified directory and walking up the directory chain.  If it finds one, it should deserialize its contents using System.Text.Json APIs and #class:'Microsoft.DotNet.Tools.Bootstrapper.GlobalJsonContentsJsonContext':413-650 , and use that for the return value.

Sorry, I meant to ask you to implement #method:'Microsoft.DotNet.Tools.Bootstrapper.DotnetInstaller.GetGlobalJsonInfo':4307-4411  instead of #method:'Microsoft.DotNet.Tools.Bootstrapper.DotnetInstaller.GetDefaultDotnetInstallPath':2839-2947 .  Can you revert your changes and then implement #method:'Microsoft.DotNet.Tools.Bootstrapper.DotnetInstaller.GetGlobalJsonInfo':4307-4411  using the instructions I previously provided?
Copilot prompts:

Can you remove the try catch block around reading the global.json file in #method:'Microsoft.DotNet.Tools.Bootstrapper.DotnetInstaller.GetGlobalJsonInfo':3019-4216 ?  Also remove the convenience properties you added to GlobalJsonInfo for now.

OK, go ahead and add those convencience properties back.
Copilot prompt:

Implement the #method:'Microsoft.DotNet.Tools.Bootstrapper.DotnetInstaller.ConfigureInstallType':4479-4606  method.  If the install type is user, remove any other folder with dotnet in it from the PATH and add the dotnetRoot to the PATH.  Also set the DOTNET_ROOT environment variable to dotnetRoot.

If the install type is Admin, unset DOTNET_ROOT, and add dotnetRoot to the path (removing any other dotnet folder from the path).

If the install type is None, unset DOTNET_ROOT and remove any dotnet folder from the path.

For any other install type, throw an ArgumentException.
Copilot prompt:

In #method:'Microsoft.DotNet.Tools.Bootstrapper.DotnetInstaller.ConfigureInstallType':4481-6459 what I meant by removing a folder from the path if it has dotnet in it was that you should check the contents of each folder and if it is a dotnet installation folder then it should be removed from the path.  A simple way to check if it's a dotnet installation folder is if it has a dotnet executable in it.
I renamed the InstallType as the Runtime installs would similarly hold the same properties.
using System.Collections.Generic;
using Microsoft.Dotnet.Installation.Internal;

namespace Microsoft.DotNet.Tools.Bootstrapper
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change oscillates between using file scoped namespaces and traditional namespace declarations. Is there a reason for not picking one style for all the files?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking a look - that's a great point.

For context, @dsplaisted raised this PR to review the prototype code we had inserted into the dnup branch, when we intended to merge into main before shipping.

Since we recently decided to ship a library, we will for now operate in the dnup branch instead. Before we ship, we want to finish reviewing the prototype code that had been merged, which is why this PR is open. I've converted the PR into a draft to better reflect this.

Back to this issue: My intention is to create a .editorconfig for dnup, and we would specify csharp_style_namespace_declarations to fix this and enforce code style such as file scoped namespaces. Similarly, if you look at the files, they have unsorted and extraneous using statements, so there's definitely a lot of clean up needed! I view it as important we enforce code style here, especially since it's easier to do so compared to the SDK which has a lot of pre-existing code, but we wanted to get a prototype first.

AssertHasFinalizationMutex();
EnsureManifestExists();

var json = File.ReadAllText(ManifestPath);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reads the entire content of the file into memory. Did you consider using a Stream for deserialization? Intuition is that is going to be more efficient.

Copy link
Member

@nagilson nagilson Oct 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a great idea. The manifest file will be very small, so I'm curious to see the numbers when we implement that. The manifest is very barebones - eventually we want a json schema file, caching, ability to upgrade / work with breaking changes to the manifest, manifest version metadata, etc. All of that is tracked in #51099, and I'll add the Stream idea, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants