mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-06 08:07:49 +00:00
fix(run): keep temporary run configurations following the toolchain settings (#1167)
Temporary run configurations were kept with what settings derived when they were made (absolute mvn, -s / -Dmaven.repo.local, JAVA_HOME), and never went through the backend again, so after a Maven home / settings file / JDK change they and gutter test runs narrowed from them still ran the old ones. They are now kept without derived values (run_without_derived) and get the current settings applied when the run list loads (run_apply_settings). Maven's settings file and local repository apply to every Maven configuration unless it sets them itself. Earlier stored entries are dropped once. Refs #822
This commit is contained in:
@@ -82,6 +82,58 @@ pub fn save_configs(
|
||||
ide_run::save_user_configs_with_removals(&project.root, &configs, removed_detected_ids)
|
||||
}
|
||||
|
||||
/// The project `config` runs in (a workspace member, by its working directory) and its settings.
|
||||
fn settings_for(
|
||||
host: &Host,
|
||||
project: &crate::project::Project,
|
||||
config: &RunConfig,
|
||||
) -> IdeResult<(std::path::PathBuf, ide_core::settings::Settings)> {
|
||||
let member = ide_workspace::workspace::Workspace::load(&project.root)?.and_then(|workspace| {
|
||||
let cwd = config.cwd.as_deref()?;
|
||||
workspace.projects.into_iter().filter(|root| cwd.starts_with(root)).max_by_key(|root| root.components().count())
|
||||
});
|
||||
Ok(match member {
|
||||
Some(root) => {
|
||||
let settings = ide_workspace::SettingsStore::load(&host.config_dir, Some(&root)).effective();
|
||||
(root, settings)
|
||||
}
|
||||
None => (project.root.clone(), project.settings.effective()),
|
||||
})
|
||||
}
|
||||
|
||||
/// Temporary configurations as they are kept between sessions: without what settings derived
|
||||
/// (toolchain commands, Maven options, `JAVA_HOME`…), so they follow later settings changes.
|
||||
pub fn without_derived(host: &Host, window: &str, configs: Vec<RunConfig>) -> IdeResult<Vec<RunConfig>> {
|
||||
host.require_trust(window)?;
|
||||
let project = host.project(window)?;
|
||||
configs
|
||||
.into_iter()
|
||||
.map(|c| {
|
||||
if c.kind == "gradle" {
|
||||
return Ok(c);
|
||||
}
|
||||
let (root, settings) = settings_for(host, &project, &c)?;
|
||||
Ok(ide_sdk::apply::without_derived(&c, &root, &settings))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Kept temporary configurations with today's settings applied, as [`configs`] lists the others.
|
||||
pub fn apply_settings(host: &Host, window: &str, configs: Vec<RunConfig>) -> IdeResult<Vec<RunConfig>> {
|
||||
host.require_trust(window)?;
|
||||
let project = host.project(window)?;
|
||||
configs
|
||||
.into_iter()
|
||||
.map(|mut c| {
|
||||
if c.kind != "gradle" {
|
||||
let (root, settings) = settings_for(host, &project, &c)?;
|
||||
ide_sdk::apply::apply_to_run_configs(std::slice::from_mut(&mut c), &root, &settings);
|
||||
}
|
||||
Ok(c)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub async fn start(host: &Host, window: &str, config: RunConfig, on_output: Emit<OutputChunk>) -> IdeResult<RunInfo> {
|
||||
host.require_trust(window)?;
|
||||
let project = host.project(window)?;
|
||||
@@ -100,15 +152,8 @@ pub async fn start(host: &Host, window: &str, config: RunConfig, on_output: Emit
|
||||
.run(&settings, &project.root, &config, project.sink.clone(), Box::new(move |c| out(c)))
|
||||
.await;
|
||||
}
|
||||
let member = ide_workspace::workspace::Workspace::load(&project.root)?.and_then(|workspace| {
|
||||
let cwd = config.cwd.as_deref()?;
|
||||
workspace.projects.into_iter().filter(|root| cwd.starts_with(root)).max_by_key(|root| root.components().count())
|
||||
});
|
||||
let root = member.as_ref().unwrap_or(&project.root);
|
||||
let settings = match &member {
|
||||
Some(root) => ide_workspace::SettingsStore::load(&host.config_dir, Some(root)).effective(),
|
||||
None => project.settings.effective(),
|
||||
};
|
||||
let (root, settings) = settings_for(host, &project, &config)?;
|
||||
let root = &root;
|
||||
// Configurations made in the UI name bare tools (`godot`) that may live outside PATH.
|
||||
let mut config = config;
|
||||
if matches!(config.kind.as_str(), "gradle" | "tomcat") {
|
||||
@@ -147,7 +192,7 @@ pub async fn start(host: &Host, window: &str, config: RunConfig, on_output: Emit
|
||||
let encoding = settings.console.encoding;
|
||||
let options = StartOptions {
|
||||
encoding: Some(encoding).filter(|e| !e.trim().is_empty()),
|
||||
python_paths: if member.is_some() { vec![root.clone()] } else { super::python::paths(&project) },
|
||||
python_paths: if *root != project.root { vec![root.clone()] } else { super::python::paths(&project) },
|
||||
};
|
||||
project.require_trust()?;
|
||||
let mut sink = project.sink.clone();
|
||||
|
||||
@@ -257,6 +257,8 @@ impl Dispatcher {
|
||||
&c.arg::<Option<Vec<String>>>("removedDetectedIds")?.unwrap_or_default(),
|
||||
)
|
||||
})
|
||||
.add("run_without_derived", |c| async move { ops::run::without_derived(&c.host, &c.window, c.arg("configs")?) })
|
||||
.add("run_apply_settings", |c| async move { ops::run::apply_settings(&c.host, &c.window, c.arg("configs")?) })
|
||||
.add("run_system_env", |_| async move { Ok(ide_run::system_env()) })
|
||||
.add("run_start", |c| async move {
|
||||
let on_output = c.channel("onOutput")?;
|
||||
|
||||
+52
-16
@@ -647,6 +647,37 @@ fn is_python_command(cmd: &str) -> bool {
|
||||
|
||||
const PY_RUNNERS: [&str; 3] = ["uv", "poetry", "pdm"];
|
||||
|
||||
/// [`maven_options`] as the groups they are passed in (`-s <file>`, `-Dmaven.repo.local=…`).
|
||||
fn maven_option_groups(options: &[String]) -> Vec<&[String]> {
|
||||
let mut groups = Vec::new();
|
||||
let mut i = 0;
|
||||
while i < options.len() {
|
||||
let n = if options[i] == "-s" { 2.min(options.len() - i) } else { 1 };
|
||||
groups.push(&options[i..i + n]);
|
||||
i += n;
|
||||
}
|
||||
groups
|
||||
}
|
||||
|
||||
/// Whether `args` set what `group` sets: a user settings file, or the local repository.
|
||||
fn sets_maven_option(args: &[String], group: &[String]) -> bool {
|
||||
match group.first().map(String::as_str) {
|
||||
Some("-s") => args.iter().any(|a| a == "-s" || a == "--settings" || a.starts_with("--settings=")),
|
||||
Some(flag) => {
|
||||
let key = flag.split_once('=').map_or(flag, |(k, _)| k);
|
||||
args.iter().any(|a| a.split_once('=').map_or(a.as_str(), |(k, _)| k) == key)
|
||||
}
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Settings › Maven's options ahead of the goals, each unless the configuration sets it itself.
|
||||
fn add_maven_options(args: &mut Vec<String>, options: &[String]) {
|
||||
let missing: Vec<String> =
|
||||
maven_option_groups(options).into_iter().filter(|g| !sets_maven_option(args, g)).flatten().cloned().collect();
|
||||
args.splice(0..0, missing);
|
||||
}
|
||||
|
||||
/// Points run configurations at the selected toolchains: Python configs use the
|
||||
/// project interpreter, npm scripts the chosen package manager and Node.js,
|
||||
/// cargo / go configs the selected toolchain, Maven / Gradle the project JDK
|
||||
@@ -783,24 +814,16 @@ pub fn apply_to_run_configs(configs: &mut [RunConfig], root: &Path, s: &Settings
|
||||
if let Some(jdk) = &jdk {
|
||||
c.env.entry("JAVA_HOME".into()).or_insert_with(|| jdk.home.to_string_lossy().into_owned());
|
||||
}
|
||||
if c.kind == "maven" && c.detected {
|
||||
if let Some(mvn) = &mvn {
|
||||
if c.kind == "maven" {
|
||||
// A configuration made or saved in the UI names the literal `mvn` /
|
||||
// `mvn.cmd`; without a wrapper it cannot start when Maven lives on a
|
||||
// version manager's shims or a configured home (#328).
|
||||
if let Some(mvn) = &mvn
|
||||
&& (c.detected || matches!(c.command.as_str(), "mvn" | "mvn.cmd" | "mvn.bat"))
|
||||
{
|
||||
c.command = mvn.to_string_lossy().into_owned();
|
||||
}
|
||||
if !c.args.starts_with(&mvn_options) {
|
||||
c.args.splice(0..0, mvn_options.iter().cloned());
|
||||
}
|
||||
} else if c.kind == "maven"
|
||||
&& matches!(c.command.as_str(), "mvn" | "mvn.cmd" | "mvn.bat")
|
||||
&& let Some(mvn) = &mvn
|
||||
{
|
||||
// A goal configuration saved from the tool window keeps the
|
||||
// literal `mvn` / `mvn.cmd` the launcher resolved to; without a
|
||||
// wrapper it cannot start when Maven lives on a version
|
||||
// manager's shims or a configured home (#328). Detected configs
|
||||
// take the Maven options too, but the saved ones already baked
|
||||
// them into `args`.
|
||||
c.command = mvn.to_string_lossy().into_owned();
|
||||
add_maven_options(&mut c.args, &mvn_options);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@@ -843,6 +866,19 @@ pub fn without_derived(config: &RunConfig, root: &Path, s: &Settings) -> RunConf
|
||||
{
|
||||
out.env.remove(&key);
|
||||
}
|
||||
// Settings › Maven's options, which applying puts back ahead of the goals.
|
||||
if out.kind == "maven" {
|
||||
let options = maven_options(root, s);
|
||||
let mut probe = out.clone();
|
||||
for group in maven_option_groups(&options) {
|
||||
if let Some(at) = probe.args.windows(group.len()).position(|w| w == group) {
|
||||
probe.args.drain(at..at + group.len());
|
||||
}
|
||||
}
|
||||
if applied(&probe).args == out.args {
|
||||
out.args = probe.args;
|
||||
}
|
||||
}
|
||||
let path = Path::new(&config.command);
|
||||
if path.is_absolute()
|
||||
&& let Some(name) = path.file_name().map(|n| n.to_string_lossy().into_owned())
|
||||
|
||||
@@ -1263,6 +1263,8 @@ fn saving_a_loaded_run_configuration_drops_what_settings_derived() {
|
||||
s.languages.java.jdk = root.join("jdk17").to_string_lossy().into_owned();
|
||||
touch("maven/bin/mvn");
|
||||
s.languages.java.maven.home = root.join("maven").to_string_lossy().into_owned();
|
||||
s.languages.java.maven.user_settings = "/m2/settings.xml".into();
|
||||
s.languages.java.maven.local_repository = "/m2/repo".into();
|
||||
s.languages.ruby.interpreter = touch("ruby/bin/ruby");
|
||||
touch("ruby/bin/bundle");
|
||||
s.tools.insert("godot".into(), ide_core::settings::ToolSettings { path: touch("Godot/godot") });
|
||||
@@ -1316,4 +1318,28 @@ fn saving_a_loaded_run_configuration_drops_what_settings_derived() {
|
||||
let ruby2 = root.join("ruby2/bin");
|
||||
assert_eq!(next.command, ruby2.join("ruby").to_string_lossy());
|
||||
assert!(next.env["PATH"].starts_with(&*ruby2.to_string_lossy()), "{}", next.env["PATH"]);
|
||||
|
||||
// A Maven configuration (a detected one narrowed to a test, a tool window goal) follows a
|
||||
// later Maven home, settings file, local repository and JDK; options it sets itself stay.
|
||||
for detected in [true, false] {
|
||||
let mut goal = saved("maven", "mvn", &["test", "-Dtest=AppTest"], &[]);
|
||||
goal.detected = detected;
|
||||
let mut own = saved("maven", "mvn", &["-s", "/mine.xml", "test"], &[]);
|
||||
own.detected = detected;
|
||||
let mut loaded = [goal, own];
|
||||
apply_to_run_configs(&mut loaded, root, &s);
|
||||
let mut next = loaded.map(|c| without_derived(&c, root, &s));
|
||||
touch("maven2/bin/mvn");
|
||||
fake_jdk(&root.join("jdk21"));
|
||||
let mut s2 = s.clone();
|
||||
s2.languages.java.maven.home = root.join("maven2").to_string_lossy().into_owned();
|
||||
s2.languages.java.maven.user_settings = "/m3/settings.xml".into();
|
||||
s2.languages.java.maven.local_repository = "/m3/repo".into();
|
||||
s2.languages.java.jdk = root.join("jdk21").to_string_lossy().into_owned();
|
||||
apply_to_run_configs(&mut next, root, &s2);
|
||||
assert_eq!(next[0].command, root.join("maven2/bin/mvn").to_string_lossy());
|
||||
assert_eq!(next[0].args, ["-s", "/m3/settings.xml", "-Dmaven.repo.local=/m3/repo", "test", "-Dtest=AppTest"]);
|
||||
assert!(next[0].env["JAVA_HOME"].ends_with("jdk21"), "{}", next[0].env["JAVA_HOME"]);
|
||||
assert_eq!(next[1].args, ["-Dmaven.repo.local=/m3/repo", "-s", "/mine.xml", "test"]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,6 +316,8 @@ pub fn builder() -> tauri_specta::Builder<tauri::Wry> {
|
||||
run::run_configs,
|
||||
run::run_dotnet_resolve,
|
||||
run::run_save_configs,
|
||||
run::run_without_derived,
|
||||
run::run_apply_settings,
|
||||
run::run_templates,
|
||||
run::run_save_templates,
|
||||
run::run_import_sources,
|
||||
|
||||
@@ -64,6 +64,34 @@ pub fn run_save_configs(
|
||||
ide_host::ops::run::save_configs(&state.host, window.label(), &configs, &removed_detected_ids.unwrap_or_default())
|
||||
}
|
||||
|
||||
/// Temporary configurations as they are kept between sessions: without what settings derived.
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn run_without_derived(
|
||||
window: Window,
|
||||
state: State<'_, AppState>,
|
||||
configs: Vec<RunConfig>,
|
||||
) -> IdeResult<Vec<RunConfig>> {
|
||||
let (host, label) = (state.host.clone(), window.label().to_owned());
|
||||
tauri::async_runtime::spawn_blocking(move || ide_host::ops::run::without_derived(&host, &label, configs))
|
||||
.await
|
||||
.map_err(|e| ide_core::IdeError::internal(e.to_string()))?
|
||||
}
|
||||
|
||||
/// Kept temporary configurations with the current settings applied.
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn run_apply_settings(
|
||||
window: Window,
|
||||
state: State<'_, AppState>,
|
||||
configs: Vec<RunConfig>,
|
||||
) -> IdeResult<Vec<RunConfig>> {
|
||||
let (host, label) = (state.host.clone(), window.label().to_owned());
|
||||
tauri::async_runtime::spawn_blocking(move || ide_host::ops::run::apply_settings(&host, &label, configs))
|
||||
.await
|
||||
.map_err(|e| ide_core::IdeError::internal(e.to_string()))?
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn run_start(
|
||||
|
||||
@@ -587,6 +587,10 @@ export const commands = {
|
||||
runConfigs: () => typedError<RunConfig_Serialize[], IdeError>(__TAURI_INVOKE("run_configs")),
|
||||
runDotnetResolve: (config: RunConfig_Deserialize, debug: boolean) => typedError<RunConfig_Serialize, IdeError>(__TAURI_INVOKE("run_dotnet_resolve", { config, debug })),
|
||||
runSaveConfigs: (configs: RunConfig_Deserialize[], removedDetectedIds: string[] | null) => typedError<null, IdeError>(__TAURI_INVOKE("run_save_configs", { configs, removedDetectedIds })),
|
||||
/** Temporary configurations as they are kept between sessions: without what settings derived. */
|
||||
runWithoutDerived: (configs: RunConfig_Deserialize[]) => typedError<RunConfig_Serialize[], IdeError>(__TAURI_INVOKE("run_without_derived", { configs })),
|
||||
/** Kept temporary configurations with the current settings applied. */
|
||||
runApplySettings: (configs: RunConfig_Deserialize[]) => typedError<RunConfig_Serialize[], IdeError>(__TAURI_INVOKE("run_apply_settings", { configs })),
|
||||
/** Configuration templates: per-type defaults applied to new configurations. */
|
||||
runTemplates: () => typedError<RunConfig_Serialize[], IdeError>(__TAURI_INVOKE("run_templates")),
|
||||
runSaveTemplates: (templates: RunConfig_Deserialize[]) => typedError<null, IdeError>(__TAURI_INVOKE("run_save_templates", { templates })),
|
||||
|
||||
@@ -391,7 +391,7 @@ describe("temporary configurations", () => {
|
||||
expect(s.temporary).not.toContain(apps[0]!.id);
|
||||
expect(s.selectedId).toBe(apps[apps.length - 1]!.id);
|
||||
expect(s.configs.filter((c) => c.kind === "application")).toHaveLength(MAX_TEMPORARY);
|
||||
expect(JSON.parse(localStorage.getItem("openidea.run.temporary:/p")!)).toHaveLength(MAX_TEMPORARY);
|
||||
expect(JSON.parse(localStorage.getItem("openidea.run.temporary.v2:/p")!)).toHaveLength(MAX_TEMPORARY);
|
||||
// Reusing an existing temporary moves it last instead of duplicating it.
|
||||
adoptTemporary(apps[3]!);
|
||||
expect(useRun.getState().temporary.at(-1)).toBe(apps[3]!.id);
|
||||
|
||||
@@ -198,7 +198,10 @@ export async function loadConfigs(): Promise<void> {
|
||||
const saved = await call(commands.runConfigs());
|
||||
if (useProject.getState().project?.root !== root) return;
|
||||
// Temporary configs survive reloads (and restarts) until saved or evicted; a saved one wins.
|
||||
const temps = readTemporary(root).filter((t) => !saved.some((c) => c.id === t.id));
|
||||
// They are kept without what settings derived: today's toolchains apply to them, as to the others.
|
||||
const kept = readTemporary(root).filter((t) => !saved.some((c) => c.id === t.id));
|
||||
const temps = kept.length ? await call(commands.runApplySettings(kept)).catch(() => kept) : kept;
|
||||
if (useProject.getState().project?.root !== root) return;
|
||||
const configs = [...saved, ...temps];
|
||||
const stored = useRun.getState().selectedId ?? readSelected(root);
|
||||
const selectedId =
|
||||
@@ -312,7 +315,8 @@ export function selectedConfig(): RunConfig | undefined {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Temporary configurations (IDEA: created by gutter / context runs, at most 5)
|
||||
|
||||
const TEMPORARY_KEY = "openidea.run.temporary:";
|
||||
// v2: kept without settings-derived values (earlier entries froze the toolchain they were made with).
|
||||
const TEMPORARY_KEY = "openidea.run.temporary.v2:";
|
||||
export const MAX_TEMPORARY = 5;
|
||||
|
||||
function readTemporary(root: string): RunConfig[] {
|
||||
@@ -335,14 +339,23 @@ function writeTemporary(root: string, configs: RunConfig[]) {
|
||||
}
|
||||
}
|
||||
|
||||
let persisting = 0;
|
||||
|
||||
function persistTemporary() {
|
||||
const root = useProject.getState().project?.root;
|
||||
if (!root) return;
|
||||
const { configs, temporary } = useRun.getState();
|
||||
writeTemporary(
|
||||
root,
|
||||
temporary.map((id) => configs.find((c) => c.id === id)).filter((c): c is RunConfig => !!c),
|
||||
);
|
||||
const list = temporary.map((id) => configs.find((c) => c.id === id)).filter((c): c is RunConfig => !!c);
|
||||
writeTemporary(root, list);
|
||||
if (!list.length || !isTauri()) return;
|
||||
// Then rewritten without what settings derived (the project's Maven, JDK, interpreter…), so a
|
||||
// later settings change reaches them as it does detected and saved configurations.
|
||||
const generation = ++persisting;
|
||||
void call(commands.runWithoutDerived(list))
|
||||
.then((kept) => {
|
||||
if (generation === persisting && useProject.getState().project?.root === root) writeTemporary(root, kept);
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
/** IDEA's `isConfigurationFromContext` for an Application: the same main class of the same module. */
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import { afterEach, beforeEach, expect, it, vi } from "vitest";
|
||||
|
||||
const ipc = vi.hoisted(() => ({
|
||||
runConfigs: vi.fn(),
|
||||
runWithoutDerived: vi.fn(),
|
||||
runApplySettings: vi.fn(),
|
||||
}));
|
||||
vi.mock("@/platform/ipc", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("@/platform/ipc")>()),
|
||||
isTauri: () => true,
|
||||
commands: ipc,
|
||||
}));
|
||||
|
||||
import type { RunConfig } from "@/platform/ipc";
|
||||
import { useProject } from "@/platform/project";
|
||||
import { adoptTemporary, loadConfigs, resetRuns, useRun } from "./store";
|
||||
|
||||
const KEY = "openidea.run.temporary.v2:/p";
|
||||
const ok = <T>(data: T) => Promise.resolve({ status: "ok" as const, data });
|
||||
|
||||
/** A Maven test run made from the tool window, with the settings of the day baked in. */
|
||||
const goal: RunConfig = {
|
||||
id: "maven:goal:pom.xml:test",
|
||||
name: "app [test]",
|
||||
kind: "maven",
|
||||
command: "/old/maven/bin/mvn",
|
||||
args: ["-s", "/old/settings.xml", "test"],
|
||||
cwd: null,
|
||||
env: { JAVA_HOME: "/old/jdk" },
|
||||
detected: false,
|
||||
isTest: true,
|
||||
debugAdapter: null,
|
||||
};
|
||||
|
||||
let mavenHome = "/new/maven";
|
||||
beforeEach(() => {
|
||||
resetRuns();
|
||||
localStorage.clear();
|
||||
useProject.setState({ project: { root: "/p" } as never });
|
||||
ipc.runConfigs.mockImplementation(() => ok([]));
|
||||
// The backend drops what settings derived, and applies the current settings again.
|
||||
ipc.runWithoutDerived.mockImplementation((configs: RunConfig[]) =>
|
||||
ok(
|
||||
configs.map((c) => ({
|
||||
...c,
|
||||
command: "mvn",
|
||||
args: c.args.filter((a, i, all) => a !== "-s" && all[i - 1] !== "-s"),
|
||||
env: {},
|
||||
})),
|
||||
),
|
||||
);
|
||||
ipc.runApplySettings.mockImplementation((configs: RunConfig[]) =>
|
||||
ok(
|
||||
configs.map((c) => ({
|
||||
...c,
|
||||
command: `${mavenHome}/bin/mvn`,
|
||||
args: ["-s", `${mavenHome}/conf/settings.xml`, ...c.args],
|
||||
env: { JAVA_HOME: "/new/jdk" },
|
||||
})),
|
||||
),
|
||||
);
|
||||
});
|
||||
afterEach(() => useProject.setState({ project: null }));
|
||||
|
||||
it("keeps temporary configurations without settings-derived values and applies today's settings on load", async () => {
|
||||
adoptTemporary(goal);
|
||||
await vi.waitFor(() => expect(JSON.parse(localStorage.getItem(KEY)!)[0].command).toBe("mvn"));
|
||||
const kept = JSON.parse(localStorage.getItem(KEY)!)[0] as RunConfig;
|
||||
expect(kept.args).toEqual(["test"]);
|
||||
expect(kept.env).toEqual({});
|
||||
|
||||
// Settings › Maven changed: the reload after it brings the temporary configuration along.
|
||||
mavenHome = "/moved/maven";
|
||||
await loadConfigs();
|
||||
const loaded = useRun.getState().configs.find((c) => c.id === goal.id)!;
|
||||
expect(useRun.getState().temporary).toEqual([goal.id]);
|
||||
expect(loaded.command).toBe("/moved/maven/bin/mvn");
|
||||
expect(loaded.args).toEqual(["-s", "/moved/maven/conf/settings.xml", "test"]);
|
||||
expect(loaded.env).toEqual({ JAVA_HOME: "/new/jdk" });
|
||||
});
|
||||
Reference in New Issue
Block a user