Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/dev-tools/backends/dotnet.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,14 @@ import Settings from '/components/settings.vue';

The following [tool-options](/dev-tools/#tool-options) are available for the `dotnet` backend—these
go in `[tools]` in `mise.toml`.

### `prerelease`

By default, NuGet pre-release versions are excluded from `mise ls-remote` and from `latest` resolution. Set `prerelease = true` to include them:

```toml
[tools]
"dotnet:GitVersion.Tool" = { version = "latest", prerelease = true }
```

The legacy `dotnet.package_flags = ["prerelease"]` setting is deprecated. Prefer the per-tool `prerelease = true` option, or the global `prereleases` setting when every tool should include pre-release versions. Because `dotnet.package_flags` is global, remove it before relying on `prerelease = false` per-tool opt-outs.
8 changes: 5 additions & 3 deletions e2e/backend/test_dotnet
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ assert_not_contains "mise ls-remote dotnet:GitVersion.Tool" "-beta"
test dotnet:GitVersion.Tool@5.12.0 "dotnet-gitversion /version" "5.12.0+Branch.support-5.x.Sha.3f75764963eb3d7956dcd5a40488c074dd9faf9e"
test dotnet:Husky@0.7.2 "husky --version" "v0.7.2"

# This command is needed if you want to reexcute the ls-remote command
# This command is needed if you want to reexecute the ls-remote command
mise cache clear

export MISE_DOTNET_PACKAGE_FLAGS="prerelease"
assert_contains "mise ls-remote 'dotnet:GitVersion.Tool[prerelease=true]'" "-beta"

assert_contains "mise ls-remote dotnet:GitVersion.Tool" "-beta"
mise cache clear

assert_contains "MISE_DOTNET_PACKAGE_FLAGS=prerelease mise ls-remote dotnet:GitVersion.Tool" "-beta"
3 changes: 2 additions & 1 deletion schema/mise.json
Original file line number Diff line number Diff line change
Expand Up @@ -710,8 +710,9 @@
},
"package_flags": {
"default": [],
"description": "Extends dotnet search and install abilities.",
"description": "[deprecated] Extends dotnet search and install abilities.",
"type": "array",
"deprecated": true,
"items": {
"type": "string"
}
Expand Down
16 changes: 11 additions & 5 deletions settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -400,13 +400,19 @@ type = "Bool"

[dotnet.package_flags]
default = []
description = "Extends dotnet search and install abilities."
deprecated = "Use the `prerelease = true` tool option or the global `prereleases` setting instead."
deprecated_remove_at = "2027.11.0"
deprecated_warn_at = "2026.11.0"
description = "[deprecated] Extends dotnet search and install abilities."
docs = """
This is a list of flags to extend the search and install abilities of dotnet tools.
Deprecated. Use the `prerelease = true` tool option on a `dotnet:` tool, or the global
`prereleases` setting, to include pre-release versions.

Here are the available flags:
This legacy setting is a list of flags to extend the search and install abilities of dotnet tools.
Because it is global, remove it before relying on `prerelease = false` per-tool opt-outs.
The only supported flag is:

- 'prerelease' : include prerelease versions in search and install
- 'prerelease' : include pre-release versions in search and install
"""
env = "MISE_DOTNET_PACKAGE_FLAGS"
parse_env = "list_by_comma"
Expand Down Expand Up @@ -1636,7 +1642,7 @@ description = "Include pre-release versions in `ls-remote`, `latest` resolution,
docs = """
By default, releases flagged `prerelease: true` on GitHub are excluded from `mise ls-remote`,
`latest` resolution, and fuzzy version matching. Per-tool opt-in is available via the
`prerelease = true` tool option (currently honored by the `github:` and `aqua:` backends).
`prerelease = true` tool option (currently honored by the `github:`, `aqua:`, and `dotnet:` backends).

Set `prereleases = true` (or `MISE_PRERELEASES=1`) to opt in globally for every tool —
equivalent to setting `prerelease = true` on each one. Useful for build pipelines that
Expand Down
6 changes: 5 additions & 1 deletion src/backend/aqua.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,11 @@ impl Backend for AquaBackend {
Ok(versions)
}

async fn latest_stable_version(&self, _config: &Arc<Config>) -> Result<Option<String>> {
async fn latest_stable_version(&self, config: &Arc<Config>) -> Result<Option<String>> {
let opts = config.get_tool_opts_with_overrides(&self.ba).await?;
if self.include_prereleases(&opts) {
return Ok(None);
}
self.latest_marked_release_version().await
}

Expand Down
6 changes: 2 additions & 4 deletions src/backend/conda.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use crate::backend::backend_type::BackendType;
use crate::backend::platform_target::PlatformTarget;
use crate::backend::{
VersionInfo, filter_cached_prereleases, include_prereleases, mark_prerelease,
};
use crate::backend::{VersionInfo, filter_cached_prereleases, mark_prerelease};
use crate::cli::args::BackendArg;
use crate::config::Config;
use crate::config::Settings;
Expand Down Expand Up @@ -676,7 +674,7 @@ impl Backend for CondaBackend {
_refresh: bool,
) -> Result<Vec<VersionInfo>> {
let opts = config.get_tool_opts_with_overrides(&self.ba).await?;
let want_prereleases = include_prereleases(&opts);
let want_prereleases = self.include_prereleases(&opts);
let versions = self
._list_remote_versions(config)
.await?
Expand Down
104 changes: 33 additions & 71 deletions src/backend/dotnet.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use std::sync::Arc;

use crate::backend::VersionInfo;
use crate::backend::backend_type::BackendType;
use crate::backend::{
VersionInfo, filter_cached_prereleases, include_prereleases, mark_prerelease,
};
use crate::cli::args::BackendArg;
use crate::cmd::CmdLineRunner;
use crate::config::Settings;
Expand All @@ -12,7 +10,6 @@ use crate::toolset::ToolVersionOptions;
use crate::{backend::Backend, config::Config};
use async_trait::async_trait;
use eyre::eyre;
use jiff::Timestamp;

/// Dotnet backend requires experimental mode to be enabled
pub const EXPERIMENTAL: bool = true;
Expand Down Expand Up @@ -40,24 +37,15 @@ impl Backend for DotnetBackend {
true
}

fn remote_version_listing_tool_option_keys(&self) -> &'static [&'static str] {
// TODO: Once dotnet remote listing always fetches the prerelease
// superset and filters at read time, remove this override entirely.
// Today `prerelease` changes the NuGet query, but there are no dotnet
// backend registry tools using the versions host.
&[]
}

async fn _list_remote_versions(&self, config: &Arc<Config>) -> eyre::Result<Vec<VersionInfo>> {
async fn _list_remote_versions(&self, _config: &Arc<Config>) -> eyre::Result<Vec<VersionInfo>> {
let feed_url = self.get_search_url().await?;
let opts = self.tool_opts(config).await?;

let feed: NugetFeedSearch = HTTP_FETCH
.json(format!(
"{}?q={}&packageType=dotnettool&take=1&prerelease={}",
feed_url,
&self.tool_name(),
self.dotnet_prereleases_enabled(&opts)
true
))
.await?;

Expand All @@ -82,53 +70,6 @@ impl Backend for DotnetBackend {
.collect())
}

/// Bypass the shared remote-versions cache because the dotnet package flags
/// affect which versions NuGet returns. The override is on `_with_refresh`
/// so install-time latest resolution uses the same dotnet-specific
/// prerelease filtering as `ls-remote`.
async fn list_remote_versions_with_info_with_refresh(
&self,
config: &Arc<Config>,
_refresh: bool,
) -> eyre::Result<Vec<VersionInfo>> {
let opts = self.tool_opts(config).await?;
let want_prereleases = self.dotnet_prereleases_enabled(&opts);
let versions = self
._list_remote_versions(config)
.await?
.into_iter()
.map(mark_prerelease)
.collect();
Ok(filter_cached_prereleases(versions, want_prereleases))
}

async fn list_versions_matching_with_opts(
&self,
config: &Arc<Config>,
query: &str,
before_date: Option<Timestamp>,
refresh: bool,
) -> eyre::Result<Vec<String>> {
let versions = match before_date {
Some(before) => {
let versions_with_info = self
.list_remote_versions_with_info_with_refresh(config, refresh)
.await?;
VersionInfo::filter_by_date(versions_with_info, before)
.into_iter()
.map(|v| v.version)
.collect()
}
None => {
self.list_remote_versions_with_refresh(config, refresh)
.await?
}
};
let opts = self.tool_opts(config).await?;
let filter = !self.dotnet_prereleases_enabled(&opts);
Ok(self.fuzzy_match_filter(versions, query, filter))
}

async fn install_version_(
&self,
ctx: &crate::install_context::InstallContext,
Expand Down Expand Up @@ -164,6 +105,15 @@ impl Backend for DotnetBackend {

Ok(tv)
}

fn include_prereleases(&self, opts: &ToolVersionOptions) -> bool {
if Settings::get().prereleases {
return true;
}

opts.opts.get("prerelease").is_some_and(tool_option_bool)
|| dotnet_legacy_prerelease_package_flag_enabled()
}
Comment thread
risu729 marked this conversation as resolved.
Comment thread
risu729 marked this conversation as resolved.
}

impl DotnetBackend {
Expand Down Expand Up @@ -191,18 +141,30 @@ impl DotnetBackend {

Ok(feed.id.clone())
}
}

async fn tool_opts(&self, config: &Arc<Config>) -> eyre::Result<ToolVersionOptions> {
config.get_tool_opts_with_overrides(&self.ba).await
fn dotnet_legacy_prerelease_package_flag_enabled() -> bool {
let enabled = Settings::get()
.dotnet
.package_flags
.iter()
.any(|flag| flag == "prerelease");
if enabled {
deprecated_at!(
"2026.11.0",
"2027.11.0",
"setting.dotnet.package_flags.prerelease",
"`dotnet.package_flags = [\"prerelease\"]` is deprecated. Use the `prerelease = true` tool option instead."
);
}
enabled
}

fn dotnet_prereleases_enabled(&self, opts: &ToolVersionOptions) -> bool {
Settings::get().prereleases
|| Settings::get()
.dotnet
.package_flags
.contains(&"prerelease".to_string())
|| include_prereleases(opts)
fn tool_option_bool(value: &toml::Value) -> bool {
match value {
toml::Value::Boolean(b) => *b,
toml::Value::String(s) => s.parse::<bool>().unwrap_or(false),
_ => false,
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/backend/github.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::install_context::InstallContext;
use crate::lockfile::{PlatformInfo, ProvenanceType};
use crate::toolset::ToolVersionOptions;
use crate::toolset::{ToolRequest, ToolVersion};
use crate::{backend::Backend, backend::include_prereleases, forgejo, github, gitlab};
use crate::{backend::Backend, forgejo, github, gitlab};
use async_trait::async_trait;
use eyre::Result;
use regex::Regex;
Expand Down Expand Up @@ -274,7 +274,7 @@ impl Backend for UnifiedGitBackend {
// defaulting to the newest non-prerelease). Returning `None` lets the
// trait's `latest_version` fall through to `latest_version_for_query`,
// which resolves against the full list — now including pre-releases.
if include_prereleases(&opts) {
if self.include_prereleases(&opts) {
return Ok(None);
}

Expand Down
Loading
Loading