-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Add design for dotnetup installation tracking #52834
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: release/dnup
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,71 @@ | ||||||
| # How to track what's installed in dotnetup | ||||||
|
|
||||||
| dotnetup should support installing various versions of the .NET SDK or runtime, as well as updating or uninstalling them. To do this, it will need to store information about what is installed in what we call the dotnetup shared manifest. | ||||||
|
|
||||||
| ## Desired behavior | ||||||
|
|
||||||
| When a user installs a .NET SDK or runtime with dotnetup, we will call the information about what the requested to be installed the "Install Spec". This includes the component that should be installed as well as the version or channel that should be installed. An install spec may also be derived from a global.json file, in which case the spec should also include the path to the corresponding global.json. | ||||||
|
|
||||||
| The effect of an update operation should be to install the latest version of the SDK or runtimes that matches each active install spec. Any installations that are no longer needed by any active install specs would then be removed. | ||||||
|
|
||||||
| An uninstall operation would be implemented as deleting an install spec and then running a garbage collection. This may not actually delete or uninstall anything if there are other install specs that resolve to the same version. In that case dotnetup should display a message explaining what happened (and what specs still refer to that version) so that the user doesn't get confused about why the version is still installed. We might also want to offer some sort of force uninstall command. | ||||||
|
|
||||||
| ## Dotnetup shared manifest contents | ||||||
|
|
||||||
| ### Install specs | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should likely provide a json schema for the manifest file as well. |
||||||
|
|
||||||
| - Component (SDK or one of the runtimes) | ||||||
| - Version, channel, or version range | ||||||
| - Source: explicit install command or global.json (could there be other sources in the future?) | ||||||
| - Global.json path | ||||||
| - Dotnet root | ||||||
|
|
||||||
| ### Installation | ||||||
| - Component | ||||||
| - Version (this is the exact version that is installed) | ||||||
| - Dotnet root | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the advantage of recording dotnet root here?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see it now but remark below that I think we should remove this |
||||||
| - Subcomponents | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Architecture is also important here
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. I haven't figured out how we'll handle architecture. I think probably each dotnet root is architecture-specific, so maybe the architecture is stored or associated with the dotnet root.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe we may also want to record the hive in which it was installed so we can properly support --directory installs. That could point to the global json path instead to reduce the amount of properties and indicate the hive is controlled by the global.json (either default hive if no sdks path specified or that path in the global.json) |
||||||
|
|
||||||
| ### Subcomponent | ||||||
|
|
||||||
| Subcomponents are sub-pieces of an installation. We need to represent these because different installed components or versions may have overlapping subcomponents. So for each installation, we will keeep a list of subcomponents that are part of that installation. | ||||||
|
||||||
| Subcomponents are sub-pieces of an installation. We need to represent these because different installed components or versions may have overlapping subcomponents. So for each installation, we will keeep a list of subcomponents that are part of that installation. | |
| Subcomponents are sub-pieces of an installation. We need to represent these because different installed components or versions may have overlapping subcomponents. So for each installation, we will keep a list of subcomponents that are part of that installation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A manifest version should also likely be included for compat / breaking changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: Do we fail if the manifest doesn't exist? I think we don't. We can try to recreate the manifest from a hive but it will never be the same - not including custom directories nor the intent of a user (e.g. explicit runtime install request vs sdk install runtime)
I also wonder if we should keep backup copies of the manifests, say in the temp folder, in case something goes wrong so we can restore the manifest. Then we get to the interesting question of 'history' like workload history but we don't need to do that for now 😁 This is probably better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may want to note that all operations against the manifest shall require a lock, or we should think about the designing the manifest in a way that enables concurrency more effectively (e.g. last writer wins.)
There are many ways to design that lock:
- Simplest : Doing any installation at all requires holding the same lock
- Directory Specific Lock - the specific hive/directory determines the lock - multiple readers/writers to the same manifest but they are working in different directories.
- Install version specific lock - enable concurrency for numerous installs across process (or instead across 1 install)
The check for which installs exist should never try to operate without holding the lock as well, so another interesting conversation is whether we want to hold read/write specific locks. (e.g. read only lock checks existing installs, but we can't get the read only lock if the write lock is taken.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we would start simply, by having an exclusive lock. I don't know if there's much user need for multiple installs happening at once, and that would make it a lot more complicated.
We may want a reader/writer lock though so that multiple windows can list what's installed at once. But maybe it's OK if we don't, the commands should execute quickly so it would be OK if they were serialized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this approach to simplify the algorithm for deleting old versions!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If dotnet_root is set to a path including installs also managed by the user, this may cause us to delete those installs. I think we likely shouldn't do this step.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Several related issues which I haven't really figured out or included in this design:
- Should we include data for multiple dotnet roots in the same manifest or have a different manifest for each root? Having everything in one manifest would let us keep track of all installs centrally. But maybe it would be better to have the manifest in each dotnet root so that the paths can be relative and things don't break if you move the dotnet root folder around.
- Should we support installing into folders with an installation that was not tracked by dotnetup? We probably wouldn't be able to handle upgrades and installations well. Some options:
- Don't support installing into folders with existing non-dnup installs at all
- Install, but only in an "untracked" mode which lays down the files but doesn't add them to a manifest and doesn't support update and uninstall.
- Create a manifest and add information to it about all the existing files. Those files should never be deleted as part of garbage collection (unless the user chooses to delete all the pre-existing installs).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Grammatical error: "what the requested to be installed" should be "what they requested to be installed" or "what was requested to be installed".