From 860aa801e0968cfcf4d17a937bd1c5cbed300848 Mon Sep 17 00:00:00 2001 From: jdx <216188+jdx@users.noreply.github.com> Date: Fri, 15 Nov 2024 21:54:23 -0600 Subject: [PATCH] feat: added `os` option to mise.toml --- .github/workflows/autofix.yml | 2 - .github/workflows/test.yml | 1 - mise.toml | 4 +- registry.toml | 1 + schema/mise.json | 23 +++- schema/mise.json.hbs | 23 +++- src/backend/asdf.rs | 8 +- src/backend/mod.rs | 43 +++++-- src/cli/install.rs | 1 + src/config/config_file/mise_toml.rs | 114 +++++++++++++----- ...fig_file__mise_toml__tests__fixture-3.snap | 19 ++- ...e__mise_toml__tests__replace_versions.snap | 2 + src/plugins/core/deno.rs | 2 +- src/plugins/core/go.rs | 2 +- src/task/deps.rs | 9 +- src/task/mod.rs | 4 +- src/toolset/mod.rs | 29 ++++- src/toolset/tool_request.rs | 92 +++++++++++--- src/toolset/tool_request_set.rs | 3 +- src/toolset/tool_version.rs | 14 ++- tasks.md | 4 +- tasks.toml | 6 +- tasks/test/coverage | 2 +- 23 files changed, 307 insertions(+), 101 deletions(-) diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml index ef222ad218..959b7eead6 100644 --- a/.github/workflows/autofix.yml +++ b/.github/workflows/autofix.yml @@ -37,6 +37,4 @@ jobs: - run: npm install - run: mise run render - run: mise run lint-fix - - run: mise run snapshots - uses: autofix-ci/action@v1.3.1 - if: ${{ always() }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4b3ebcbfa4..4d69c456f7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -174,7 +174,6 @@ jobs: - run: cargo test continue-on-error: true - run: mise install - continue-on-error: true - run: mise test-tool --all continue-on-error: true windows-e2e: diff --git a/mise.toml b/mise.toml index e804dd15ff..b007879167 100644 --- a/mise.toml +++ b/mise.toml @@ -10,7 +10,7 @@ shfmt = "3" jq = "latest" cargo-binstall = "latest" "cargo:cargo-edit" = "latest" -"cargo:cargo-show" = "latest" +"cargo:cargo-show" = {version = "latest", os = ["linux", "macos"]} "cargo:cargo-insta" = "latest" "cargo:git-cliff" = "latest" "npm:markdownlint-cli" = "latest" @@ -19,7 +19,7 @@ direnv = "latest" actionlint = "latest" ripgrep = "latest" "pipx:toml-sort" = "latest" -"cargo:usage-cli" = "1.3" +"cargo:usage-cli" = {version = "1.3", os = ["linux", "macos"]} #python = { version = "latest", virtualenv = "{{env.HOME}}/.cache/venv" } [task_config] diff --git a/registry.toml b/registry.toml index 55314bad25..1915f3ef0f 100644 --- a/registry.toml +++ b/registry.toml @@ -776,6 +776,7 @@ updatecli.backends = ["aqua:updatecli/updatecli", "asdf:updatecli/asdf-updatecli upt.backends = ["asdf:ORCID/asdf-upt"] upx.backends = ["asdf:jimmidyson/asdf-upx"] usage.backends = ["ubi:jdx/usage", "asdf:jdx/mise-usage"] +usage.os = ["linux", "macos"] usql.backends = ["aqua:xo/usql", "asdf:itspngu/asdf-usql"] uv.backends = ["aqua:astral-sh/uv", "asdf:asdf-community/asdf-uv"] v.backends = ["asdf:jthegedus/asdf-v"] diff --git a/schema/mise.json b/schema/mise.json index f6542d39ef..0571f58eb6 100644 --- a/schema/mise.json +++ b/schema/mise.json @@ -763,16 +763,35 @@ "version": { "description": "version of the tool to install", "type": "string" + }, + "os": { + "oneOf": [ + { + "description": "operating system to install on", + "type": "array" + }, + { + "description": "option to pass to tool", + "type": "string" + } + ] } }, "required": ["version"], - "type": "object" + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "string" + } + ] + } } ] } }, "additionalProperties": false, - "description": "config file for mise version manager (.mise.toml)", + "description": "config file for mise version manager (mise.toml)", "properties": { "alias": { "additionalProperties": { diff --git a/schema/mise.json.hbs b/schema/mise.json.hbs index e9cee3ce46..b08b795401 100644 --- a/schema/mise.json.hbs +++ b/schema/mise.json.hbs @@ -277,18 +277,37 @@ "version": { "description": "version of the tool to install", "type": "string" + }, + "os": { + "oneOf": [ + { + "description": "operating system to install on", + "type": "array" + }, + { + "description": "option to pass to tool", + "type": "string" + } + ] } }, "required": [ "version" ], - "type": "object" + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "string" + } + ] + } } ] } }, "additionalProperties": false, - "description": "config file for mise version manager (.mise.toml)", + "description": "config file for mise version manager (mise.toml)", "properties": { "alias": { "additionalProperties": { diff --git a/src/backend/asdf.rs b/src/backend/asdf.rs index 953df7cd20..a8d40387f8 100644 --- a/src/backend/asdf.rs +++ b/src/backend/asdf.rs @@ -119,7 +119,7 @@ impl AsdfBackend { fn fetch_bin_paths(&self, tv: &ToolVersion) -> Result> { let list_bin_paths = self.plugin_path.join("bin/list-bin-paths"); - let bin_paths = if matches!(tv.request, ToolRequest::System(..)) { + let bin_paths = if matches!(tv.request, ToolRequest::System { .. }) { Vec::new() } else if list_bin_paths.exists() { let sm = self.script_man_for_tv(tv)?; @@ -184,9 +184,9 @@ impl AsdfBackend { let install_type = match &tv.request { ToolRequest::Version { .. } | ToolRequest::Prefix { .. } => "version", ToolRequest::Ref { .. } => "ref", - ToolRequest::Path(..) => "path", + ToolRequest::Path { .. } => "path", ToolRequest::Sub { .. } => "sub", - ToolRequest::System(..) => { + ToolRequest::System { .. } => { panic!("should not be called for system tool") } }; @@ -384,7 +384,7 @@ impl Backend for AsdfBackend { ts: &Toolset, tv: &ToolVersion, ) -> eyre::Result> { - if matches!(tv.request, ToolRequest::System(..)) { + if matches!(tv.request, ToolRequest::System { .. }) { return Ok(BTreeMap::new()); } if !self.plugin.script_man.script_exists(&ExecEnv) || *env::__MISE_SCRIPT { diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 0c8546a6bd..0a89fa4129 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -193,7 +193,11 @@ pub trait Backend: Debug + Send + Sync { .collect::>(); for dep in dep_backends { // TODO: pass the right tvr - let tvr = ToolRequest::System(dep.id().into(), ToolSource::Unknown); + let tvr = ToolRequest::System { + backend: dep.id().into(), + source: ToolSource::Unknown, + os: None, + }; deps.extend(dep.get_all_dependencies(&tvr)?); } Ok(deps.into_iter().collect()) @@ -242,7 +246,7 @@ pub trait Backend: Debug + Send + Sync { } fn is_version_installed(&self, tv: &ToolVersion, check_symlink: bool) -> bool { match tv.request { - ToolRequest::System(..) => true, + ToolRequest::System { .. } => true, _ => { let check_path = |install_path: &Path| { let is_installed = install_path.exists(); @@ -338,7 +342,11 @@ pub trait Backend: Debug + Send + Sync { fn ensure_dependencies_installed(&self) -> eyre::Result<()> { let deps = self - .get_all_dependencies(&ToolRequest::System(self.id().into(), ToolSource::Unknown))? + .get_all_dependencies(&ToolRequest::System { + backend: self.id().into(), + source: ToolSource::Unknown, + os: None, + })? .into_iter() .collect::>(); if !deps.is_empty() { @@ -474,7 +482,7 @@ pub trait Backend: Debug + Send + Sync { } fn list_bin_paths(&self, tv: &ToolVersion) -> eyre::Result> { match tv.request { - ToolRequest::System(..) => Ok(vec![]), + ToolRequest::System { .. } => Ok(vec![]), _ => Ok(vec![tv.install_path().join("bin")]), } } @@ -494,9 +502,21 @@ pub trait Backend: Debug + Send + Sync { .into_iter() .filter(|p| p.parent().is_some()); for bin_path in bin_paths { - let bin_path = bin_path.join(bin_name); - if bin_path.exists() { - return Ok(Some(bin_path)); + let paths_with_ext = if cfg!(windows) { + vec![ + bin_path.clone(), + bin_path.join(bin_name).with_extension("exe"), + bin_path.join(bin_name).with_extension("cmd"), + bin_path.join(bin_name).with_extension("bat"), + bin_path.join(bin_name).with_extension("ps1"), + ] + } else { + vec![bin_path.join(bin_name)] + }; + for bin_path in paths_with_ext { + if bin_path.exists() && file::is_executable(&bin_path) { + return Ok(Some(bin_path)); + } } } Ok(None) @@ -531,10 +551,11 @@ pub trait Backend: Debug + Send + Sync { fn dependency_toolset(&self) -> eyre::Result { let config = Config::get(); let dependencies = self - .get_all_dependencies(&ToolRequest::System( - self.name().into(), - ToolSource::Unknown, - ))? + .get_all_dependencies(&ToolRequest::System { + backend: self.name().into(), + source: ToolSource::Unknown, + os: None, + })? .into_iter() .collect(); let mut ts: Toolset = config diff --git a/src/cli/install.rs b/src/cli/install.rs index 7db0db1e60..91aa76434b 100644 --- a/src/cli/install.rs +++ b/src/cli/install.rs @@ -110,6 +110,7 @@ impl Install { let tvr = ToolRequest::Version { backend: ta.ba.clone(), version: "latest".into(), + os: None, options: ta.opts.clone().unwrap_or(Default::default()), source: ToolSource::Argument, }; diff --git a/src/config/config_file/mise_toml.rs b/src/config/config_file/mise_toml.rs index 9199b8c2f7..e67ec7ab79 100644 --- a/src/config/config_file/mise_toml.rs +++ b/src/config/config_file/mise_toml.rs @@ -62,6 +62,7 @@ pub struct MiseTomlToolList(Vec); #[derive(Debug, Clone)] pub struct MiseTomlTool { pub tt: ToolVersionType, + pub os: Option>, pub options: Option, } @@ -313,6 +314,7 @@ impl ConfigFile for MiseToml { .iter() .map(|(v, opts)| MiseTomlTool { tt: ToolVersionType::Version(v.clone()), + os: None, // TODO: use existing os options: if !output_empty_opts(opts) { Some(opts.clone()) } else { @@ -391,16 +393,16 @@ impl ConfigFile for MiseToml { trust_check(&self.path)?; } let version = self.parse_template(&tool.tt.to_string())?; - if let Some(mut options) = tool.options.clone() { + let mut tvr = if let Some(mut options) = tool.options.clone() { for v in options.values_mut() { *v = self.parse_template(v)?; } - let tvr = ToolRequest::new_opts(fa.clone(), &version, options, source.clone())?; - trs.add_version(tvr, &source); + ToolRequest::new_opts(fa.clone(), &version, options, source.clone())? } else { - let tvr = ToolRequest::new(fa.clone(), &version, source.clone())?; - trs.add_version(tvr, &source); - } + ToolRequest::new(fa.clone(), &version, source.clone())? + }; + tvr = tvr.with_os(tool.os.clone()); + trs.add_version(tvr, &source); } } Ok(trs) @@ -759,7 +761,11 @@ impl<'de> de::Deserialize<'de> for MiseTomlToolList { let tt: ToolVersionType = v .parse() .map_err(|e| de::Error::custom(format!("invalid tool: {e}")))?; - Ok(MiseTomlToolList(vec![MiseTomlTool { tt, options: None }])) + Ok(MiseTomlToolList(vec![MiseTomlTool { + tt, + os: None, + options: None, + }])) } fn visit_seq(self, mut seq: S) -> std::result::Result @@ -773,22 +779,44 @@ impl<'de> de::Deserialize<'de> for MiseTomlToolList { Ok(MiseTomlToolList(tools)) } - fn visit_map(self, map: M) -> std::result::Result + fn visit_map(self, mut map: M) -> std::result::Result where M: de::MapAccess<'de>, { - let mut options: BTreeMap = - de::Deserialize::deserialize(de::value::MapAccessDeserializer::new(map))?; - let tt: ToolVersionType = options - .remove("version") - .or_else(|| options.remove("path").map(|p| format!("path:{p}"))) - .or_else(|| options.remove("prefix").map(|p| format!("prefix:{p}"))) - .or_else(|| options.remove("ref").map(|p| format!("ref:{p}"))) - .ok_or_else(|| de::Error::custom("missing version"))? - .parse() - .map_err(de::Error::custom)?; + let mut options: BTreeMap = Default::default(); + let mut os: Option> = None; + let mut tt = ToolVersionType::System; + while let Some((k, v)) = map.next_entry::()? { + match k.as_str() { + "version" => { + tt = v.as_str().unwrap().parse().map_err(de::Error::custom)?; + } + "path" | "prefix" | "ref" => { + tt = format!("{k}:{}", v.as_str().unwrap()) + .parse() + .map_err(de::Error::custom)?; + } + "os" => match v { + toml::Value::Array(s) => { + os = Some( + s.iter().map(|v| v.as_str().unwrap().to_string()).collect(), + ); + } + toml::Value::String(s) => { + options.insert(k, s); + } + _ => { + return Err(de::Error::custom("os must be a string or array")); + } + }, + _ => { + options.insert(k, v.as_str().unwrap().to_string()); + } + } + } Ok(MiseTomlToolList(vec![MiseTomlTool { tt, + os, options: Some(options), }])) } @@ -818,25 +846,51 @@ impl<'de> de::Deserialize<'de> for MiseTomlTool { let tt: ToolVersionType = v .parse() .map_err(|e| de::Error::custom(format!("invalid tool: {e}")))?; - Ok(MiseTomlTool { tt, options: None }) + Ok(MiseTomlTool { + tt, + os: None, + options: None, + }) } - fn visit_map(self, map: M) -> Result + fn visit_map(self, mut map: M) -> Result where M: de::MapAccess<'de>, { - let mut options: BTreeMap = - de::Deserialize::deserialize(de::value::MapAccessDeserializer::new(map))?; - let tt: ToolVersionType = options - .remove("version") - .or_else(|| options.remove("path").map(|p| format!("path:{p}"))) - .or_else(|| options.remove("prefix").map(|p| format!("prefix:{p}"))) - .or_else(|| options.remove("ref").map(|p| format!("ref:{p}"))) - .ok_or_else(|| de::Error::custom("missing version"))? - .parse() - .map_err(de::Error::custom)?; + let mut options: BTreeMap = Default::default(); + let mut os: Option> = None; + let mut tt = ToolVersionType::System; + while let Some((k, v)) = map.next_entry::()? { + match k.as_str() { + "version" => { + tt = v.as_str().unwrap().parse().map_err(de::Error::custom)?; + } + "path" | "prefix" | "ref" => { + tt = format!("{k}:{}", v.as_str().unwrap()) + .parse() + .map_err(de::Error::custom)?; + } + "os" => match v { + toml::Value::Array(s) => { + os = Some( + s.iter().map(|v| v.as_str().unwrap().to_string()).collect(), + ); + } + toml::Value::String(s) => { + options.insert(k, s); + } + _ => { + return Err(de::Error::custom("os must be a string or array")); + } + }, + _ => { + options.insert(k, v.as_str().unwrap().to_string()); + } + } + } Ok(MiseTomlTool { tt, + os, options: Some(options), }) } diff --git a/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__fixture-3.snap b/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__fixture-3.snap index 4985c04b17..16270762ba 100644 --- a/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__fixture-3.snap +++ b/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__fixture-3.snap @@ -13,6 +13,7 @@ ToolRequestSet { source: MiseToml( "~/fixtures/.mise.toml", ), + os: None, }, ], BackendArg("node" -> "core:node"): [ @@ -23,6 +24,7 @@ ToolRequestSet { source: MiseToml( "~/fixtures/.mise.toml", ), + os: None, }, Prefix { backend: BackendArg("node" -> "core:node"), @@ -31,6 +33,7 @@ ToolRequestSet { source: MiseToml( "~/fixtures/.mise.toml", ), + os: None, }, Ref { backend: BackendArg("node" -> "core:node"), @@ -40,14 +43,16 @@ ToolRequestSet { source: MiseToml( "~/fixtures/.mise.toml", ), + os: None, }, - Path( - BackendArg("node" -> "core:node"), - "~/.nodes/18", - MiseToml( + Path { + backend: BackendArg("node" -> "core:node"), + path: "~/.nodes/18", + source: MiseToml( "~/fixtures/.mise.toml", ), - ), + os: None, + }, ], BackendArg("jq" -> "aqua:jqlang/jq"): [ Prefix { @@ -57,6 +62,7 @@ ToolRequestSet { source: MiseToml( "~/fixtures/.mise.toml", ), + os: None, }, ], BackendArg("shellcheck" -> "ubi:koalaman/shellcheck"): [ @@ -67,6 +73,7 @@ ToolRequestSet { source: MiseToml( "~/fixtures/.mise.toml", ), + os: None, }, ], BackendArg("python" -> "core:python"): [ @@ -79,6 +86,7 @@ ToolRequestSet { source: MiseToml( "~/fixtures/.mise.toml", ), + os: None, }, Version { backend: BackendArg("python" -> "core:python"), @@ -87,6 +95,7 @@ ToolRequestSet { source: MiseToml( "~/fixtures/.mise.toml", ), + os: None, }, ], }, diff --git a/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__replace_versions.snap b/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__replace_versions.snap index 99ee109f18..15611e8bc2 100644 --- a/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__replace_versions.snap +++ b/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__replace_versions.snap @@ -16,6 +16,7 @@ Toolset { source: MiseToml( "/tmp/.mise.toml", ), + os: None, }, Version { backend: BackendArg("node" -> "core:node"), @@ -24,6 +25,7 @@ Toolset { source: MiseToml( "/tmp/.mise.toml", ), + os: None, }, ], source: MiseToml( diff --git a/src/plugins/core/deno.rs b/src/plugins/core/deno.rs index 0f985b6682..715d1a43bd 100644 --- a/src/plugins/core/deno.rs +++ b/src/plugins/core/deno.rs @@ -119,7 +119,7 @@ impl Backend for DenoPlugin { } fn list_bin_paths(&self, tv: &ToolVersion) -> Result> { - if let ToolRequest::System(..) = tv.request { + if let ToolRequest::System { .. } = tv.request { return Ok(vec![]); } let bin_paths = vec![ diff --git a/src/plugins/core/go.rs b/src/plugins/core/go.rs index 6a8cc0baa6..6bbcccfe03 100644 --- a/src/plugins/core/go.rs +++ b/src/plugins/core/go.rs @@ -215,7 +215,7 @@ impl Backend for GoPlugin { } fn list_bin_paths(&self, tv: &ToolVersion) -> eyre::Result> { - if let ToolRequest::System(..) = tv.request { + if let ToolRequest::System { .. } = tv.request { return Ok(vec![]); } // goroot/bin must always be included, irrespective of MISE_GO_SET_GOROOT diff --git a/src/task/deps.rs b/src/task/deps.rs index 2aac63b096..cb2c67a1bf 100644 --- a/src/task/deps.rs +++ b/src/task/deps.rs @@ -28,11 +28,18 @@ impl Deps { .entry(t.name.clone()) .or_insert_with(|| graph.add_node(t.clone())); } + let all_tasks_to_run = tasks + .iter() + .flat_map(|t| { + [t].into_iter() + .chain(t.resolve_depends(&CONFIG, &[]).unwrap_or_default()) + }) + .collect_vec(); while let Some(a) = stack.pop() { let a_idx = *indexes .entry(a.name.clone()) .or_insert_with(|| graph.add_node(a.clone())); - for b in a.resolve_depends(&CONFIG, &tasks)? { + for b in a.resolve_depends(&CONFIG, &all_tasks_to_run)? { let b_idx = *indexes .entry(b.name.clone()) .or_insert_with(|| graph.add_node(b.clone())); diff --git a/src/task/mod.rs b/src/task/mod.rs index 5d90a0d1c1..05d6654bd6 100644 --- a/src/task/mod.rs +++ b/src/task/mod.rs @@ -172,9 +172,9 @@ impl Task { pub fn resolve_depends<'a>( &self, config: &'a Config, - tasks_to_run: &[Task], + tasks_to_run: &[&Task], ) -> Result> { - let tasks_to_run: HashSet<&Task> = tasks_to_run.iter().collect(); + let tasks_to_run: HashSet<&Task> = tasks_to_run.iter().copied().collect(); let tasks = config.tasks_with_aliases()?; self.wait_for .iter() diff --git a/src/toolset/mod.rs b/src/toolset/mod.rs index 04177c90d9..d4d73b6b01 100644 --- a/src/toolset/mod.rs +++ b/src/toolset/mod.rs @@ -152,8 +152,14 @@ impl Toolset { pub fn list_missing_plugins(&self) -> Vec { self.versions - .keys() - .filter(|ba| ba.is_os_supported()) + .iter() + .filter(|(_, tvl)| { + tvl.versions + .first() + .map(|tv| tv.request.is_os_supported()) + .unwrap_or_default() + }) + .map(|(ba, _)| ba) .flat_map(|ba| ba.backend()) .filter(|b| b.plugin().is_some_and(|p| !p.is_installed())) .map(|p| p.id().into()) @@ -234,7 +240,8 @@ impl Toolset { tv: tv.clone(), force: opts.force, }; - t.install_version(ctx)?; + t.install_version(ctx) + .wrap_err_with(|| format!("failed to install {tv}"))?; installed.push(tv); } installing.lock().unwrap().remove(t.id()); @@ -289,7 +296,14 @@ impl Toolset { pub fn list_missing_versions(&self) -> Vec { self.list_current_versions() .into_iter() - .filter(|(p, tv)| tv.ba().is_os_supported() && !p.is_version_installed(tv, true)) + .filter(|(p, tv)| { + if let Some(os) = tv.request.os() { + if !os.contains(&crate::cli::version::OS) { + return false; + } + } + tv.request.is_os_supported() && !p.is_version_installed(tv, true) + }) .map(|(_, tv)| tv) .collect() } @@ -349,6 +363,7 @@ impl Toolset { backend: p.ba().clone(), ref_: r.to_string(), ref_type: ref_type.to_string(), + os: v.request.os().clone(), options: v.request.options().clone(), source: v.request.source().clone(), }; @@ -425,12 +440,14 @@ impl Toolset { version: _version, options, source, + os, } => { out.tool_request = ToolRequest::Version { backend, options, source, version: out.bump.clone().unwrap(), + os, }; } _ => { @@ -473,7 +490,7 @@ impl Toolset { let entries = self .list_current_installed_versions() .into_par_iter() - .filter(|(_, tv)| !matches!(tv.request, ToolRequest::System(..))) + .filter(|(_, tv)| !matches!(tv.request, ToolRequest::System { .. })) .flat_map(|(p, tv)| match p.exec_env(config, self, &tv) { Ok(env) => env.into_iter().collect(), Err(e) => { @@ -506,7 +523,7 @@ impl Toolset { pub fn list_paths(&self) -> Vec { self.list_current_installed_versions() .into_par_iter() - .filter(|(_, tv)| !matches!(tv.request, ToolRequest::System(..))) + .filter(|(_, tv)| !matches!(tv.request, ToolRequest::System { .. })) .flat_map(|(p, tv)| { p.list_bin_paths(&tv).unwrap_or_else(|e| { warn!("Error listing bin paths for {tv}: {e:#}"); diff --git a/src/toolset/tool_request.rs b/src/toolset/tool_request.rs index 134096eff0..f95c714c61 100644 --- a/src/toolset/tool_request.rs +++ b/src/toolset/tool_request.rs @@ -19,12 +19,14 @@ pub enum ToolRequest { version: String, options: ToolVersionOptions, source: ToolSource, + os: Option>, }, Prefix { backend: BackendArg, prefix: String, options: ToolVersionOptions, source: ToolSource, + os: Option>, }, Ref { backend: BackendArg, @@ -32,15 +34,26 @@ pub enum ToolRequest { ref_type: String, options: ToolVersionOptions, source: ToolSource, + os: Option>, }, Sub { backend: BackendArg, sub: String, orig_version: String, source: ToolSource, + os: Option>, + }, + Path { + backend: BackendArg, + path: PathBuf, + source: ToolSource, + os: Option>, + }, + System { + backend: BackendArg, + source: ToolSource, + os: Option>, }, - Path(BackendArg, PathBuf, ToolSource), - System(BackendArg, ToolSource), } impl ToolRequest { @@ -54,28 +67,41 @@ impl ToolRequest { ref_: r.to_string(), ref_type: ref_type.to_string(), options: backend.opts.clone().unwrap_or_default(), + os: None, backend, source, }, Some(("prefix", p)) => Self::Prefix { prefix: p.to_string(), options: backend.opts.clone().unwrap_or_default(), + os: None, backend, source, }, - Some(("path", p)) => Self::Path(backend, PathBuf::from(p), source), + Some(("path", p)) => Self::Path { + backend, + path: PathBuf::from(p), + source, + os: None, + }, Some((p, v)) if p.starts_with("sub-") => Self::Sub { sub: p.split_once('-').unwrap().1.to_string(), orig_version: v.to_string(), + os: None, backend, source, }, None => { if s == "system" { - Self::System(backend, source) + Self::System { + backend, + source, + os: None, + } } else { Self::Version { version: s, + os: None, options: backend.opts.clone().unwrap_or_default(), backend, source, @@ -105,20 +131,20 @@ impl ToolRequest { Self::Version { source: s, .. } | Self::Prefix { source: s, .. } | Self::Ref { source: s, .. } - | Self::Path(_, _, s) + | Self::Path { source: s, .. } | Self::Sub { source: s, .. } - | Self::System(_, s) => *s = source, + | Self::System { source: s, .. } => *s = source, } self.clone() } pub fn ba(&self) -> &BackendArg { match self { - Self::Version { backend: f, .. } - | Self::Prefix { backend: f, .. } - | Self::Ref { backend: f, .. } - | Self::Path(f, ..) - | Self::Sub { backend: f, .. } - | Self::System(f, ..) => f, + Self::Version { backend, .. } + | Self::Prefix { backend, .. } + | Self::Ref { backend, .. } + | Self::Path { backend, .. } + | Self::Sub { backend, .. } + | Self::System { backend, .. } => backend, } } pub fn backend(&self) -> Result { @@ -129,10 +155,31 @@ impl ToolRequest { Self::Version { source, .. } | Self::Prefix { source, .. } | Self::Ref { source, .. } - | Self::Path(.., source) + | Self::Path { source, .. } | Self::Sub { source, .. } - | Self::System(_, source) => source, + | Self::System { source, .. } => source, + } + } + pub fn os(&self) -> &Option> { + match self { + Self::Version { os, .. } + | Self::Prefix { os, .. } + | Self::Ref { os, .. } + | Self::Path { os, .. } + | Self::Sub { os, .. } + | Self::System { os, .. } => os, + } + } + pub fn with_os(mut self, os: Option>) -> Self { + match &mut self { + Self::Version { os: o, .. } + | Self::Prefix { os: o, .. } + | Self::Ref { os: o, .. } + | Self::Path { os: o, .. } + | Self::Sub { os: o, .. } + | Self::System { os: o, .. } => *o = os, } + self } pub fn dependencies(&self) -> eyre::Result> { let backend = self.ba().backend()?; @@ -145,11 +192,11 @@ impl ToolRequest { Self::Ref { ref_: r, ref_type, .. } => format!("{ref_type}:{r}"), - Self::Path(_, p, ..) => format!("path:{}", p.display()), + Self::Path { path: p, .. } => format!("path:{}", p.display()), Self::Sub { sub, orig_version, .. } => format!("sub-{}:{}", sub, orig_version), - Self::System(..) => "system".to_string(), + Self::System { .. } => "system".to_string(), } } @@ -204,8 +251,8 @@ impl ToolRequest { .cloned(), Err(_) => None, }, - Self::Path(_, path, ..) => Some(path.clone()), - Self::System(..) => None, + Self::Path { path, .. } => Some(path.clone()), + Self::System { .. } => None, } } @@ -235,6 +282,15 @@ impl ToolRequest { pub fn resolve(&self, opts: &ResolveOptions) -> Result { ToolVersion::resolve(self.clone(), opts) } + + pub fn is_os_supported(&self) -> bool { + if let Some(os) = self.os() { + if !os.contains(&crate::cli::version::OS) { + return false; + } + } + self.ba().is_os_supported() + } } /// subtracts sub from orig and removes suffix diff --git a/src/toolset/tool_request_set.rs b/src/toolset/tool_request_set.rs index ff007e6fbf..485b1f8bf2 100644 --- a/src/toolset/tool_request_set.rs +++ b/src/toolset/tool_request_set.rs @@ -43,8 +43,7 @@ impl ToolRequestSet { self.tools .values() .flatten() - .filter(|tr| tr.ba().is_os_supported()) - .filter(|tvr| !tvr.is_installed()) + .filter(|tr| tr.is_os_supported() && !tr.is_installed()) .collect() } diff --git a/src/toolset/tool_version.rs b/src/toolset/tool_version.rs index 9b9f02aee5..9a89d68377 100644 --- a/src/toolset/tool_version.rs +++ b/src/toolset/tool_version.rs @@ -66,7 +66,7 @@ impl ToolVersion { pub fn install_path(&self) -> PathBuf { let pathname = match &self.request { - ToolRequest::Path(_, p, ..) => p.to_string_lossy().to_string(), + ToolRequest::Path { path: p, .. } => p.to_string_lossy().to_string(), _ => self.tv_pathname(), }; let path = self.ba().installs_path.join(pathname); @@ -121,8 +121,8 @@ impl ToolVersion { ToolRequest::Prefix { .. } => self.version.to_string(), ToolRequest::Sub { .. } => self.version.to_string(), ToolRequest::Ref { ref_: r, .. } => format!("ref-{}", r), - ToolRequest::Path(_, p, ..) => format!("path-{}", hash_to_str(p)), - ToolRequest::System(..) => "system".to_string(), + ToolRequest::Path { path: p, .. } => format!("path-{}", hash_to_str(p)), + ToolRequest::System { .. } => "system".to_string(), } .replace([':', '/'], "-") } @@ -226,6 +226,7 @@ impl ToolVersion { backend: tr.ba().clone(), ref_, ref_type, + os: None, options: opts.clone(), source: tr.source().clone(), }; @@ -235,7 +236,12 @@ impl ToolVersion { fn resolve_path(path: PathBuf, tr: &ToolRequest) -> Result { let path = fs::canonicalize(path)?; - let request = ToolRequest::Path(tr.ba().clone(), path, tr.source().clone()); + let request = ToolRequest::Path { + backend: tr.ba().clone(), + path, + source: tr.source().clone(), + os: None, + }; let version = request.version(); Ok(Self::new(request, version)) } diff --git a/tasks.md b/tasks.md index 002413f8c3..e7e18ee3b1 100644 --- a/tasks.md +++ b/tasks.md @@ -154,14 +154,12 @@ User to run as ## `render:completions` -- Depends: build, render:usage +- Depends: build - **Usage**: `render:completions` ## `render:fig` -- Depends: build, render:usage - - **Usage**: `render:fig` ## `render:help` diff --git a/tasks.toml b/tasks.toml index 641f7d31f7..2080c92487 100644 --- a/tasks.toml +++ b/tasks.toml @@ -7,7 +7,7 @@ lint = { depends = ["lint:*"] } [build] alias = "b" -run = "cargo build --color always --all-features" +run = "cargo build --all-features" #sources = ["Cargo.*", "src/**/*.rs"] #outputs = ["target/debug/mise"] @@ -22,7 +22,8 @@ run = [ ] ["render:completions"] -depends = ["build", "render:usage"] +depends = ["build"] +wait_for = ["render:usage"] env = { NO_COLOR = "1" } run = ''' #!/usr/bin/env bash @@ -45,7 +46,6 @@ env = { NO_COLOR = "1" } run = "mise render-mangen" ["render:fig"] -depends = ["build", "render:usage"] wait_for = ["render:completions"] run = [ "usage generate fig --file mise.usage.kdl --out-file tasks/fig/src/mise.ts", diff --git a/tasks/test/coverage b/tasks/test/coverage index a5660f64ec..fb0cf69b85 100755 --- a/tasks/test/coverage +++ b/tasks/test/coverage @@ -30,7 +30,7 @@ elif [[ "${TEST_TRANCHE:-}" == 1 ]]; then m=12 y=$((y - 1)) fi - mise self-update -fy "$y.$m.0" + mise self-update -fy "$y.$m.0" || true elif [[ "${TEST_TRANCHE:-}" == 3 ]]; then echo "::group::Unit tests" cargo test --all-features