mirror of
https://github.com/tauri-apps/tauri.git
synced 2025-01-01 23:42:33 +03:00
This commit is contained in:
parent
90d5929fea
commit
d6f7d3cfe8
7
.changes/before-command-cwd.md
Normal file
7
.changes/before-command-cwd.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
"tauri-utils": minor
|
||||
"cli.rs": minor
|
||||
"cli.js": minor
|
||||
---
|
||||
|
||||
Change `before_dev_command` and `before_build_command` config value to allow configuring the current working directory.
|
7
.changes/before-dev-command-wait.md
Normal file
7
.changes/before-dev-command-wait.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
"tauri-utils": minor
|
||||
"cli.rs": minor
|
||||
"cli.js": minor
|
||||
---
|
||||
|
||||
Allow configuring the `before_dev_command` to force the CLI to wait for the command to finish before proceeding.
|
@ -2377,6 +2377,41 @@ impl std::fmt::Display for AppUrl {
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes the shell command to run before `tauri dev`.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
|
||||
#[cfg_attr(feature = "schema", derive(JsonSchema))]
|
||||
#[serde(rename_all = "camelCase", untagged)]
|
||||
pub enum BeforeDevCommand {
|
||||
/// Run the given script with the default options.
|
||||
Script(String),
|
||||
/// Run the given script with custom options.
|
||||
ScriptWithOptions {
|
||||
/// The script to execute.
|
||||
script: String,
|
||||
/// The current working directory.
|
||||
cwd: Option<String>,
|
||||
/// Whether `tauri dev` should wait for the command to finish or not. Defaults to `false`.
|
||||
#[serde(default)]
|
||||
wait: bool,
|
||||
},
|
||||
}
|
||||
|
||||
/// Describes the shell command to run before `tauri build`.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
|
||||
#[cfg_attr(feature = "schema", derive(JsonSchema))]
|
||||
#[serde(rename_all = "camelCase", untagged)]
|
||||
pub enum BeforeBuildCommand {
|
||||
/// Run the given script with the default options.
|
||||
Script(String),
|
||||
/// Run the given script with custom options.
|
||||
ScriptWithOptions {
|
||||
/// The script to execute.
|
||||
script: String,
|
||||
/// The current working directory.
|
||||
cwd: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
/// The Build configuration object.
|
||||
#[skip_serializing_none]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
|
||||
@ -2411,12 +2446,12 @@ pub struct BuildConfig {
|
||||
///
|
||||
/// The TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG environment variables are set if you perform conditional compilation.
|
||||
#[serde(alias = "before-dev-command")]
|
||||
pub before_dev_command: Option<String>,
|
||||
pub before_dev_command: Option<BeforeDevCommand>,
|
||||
/// A shell command to run before `tauri build` kicks in.
|
||||
///
|
||||
/// The TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG environment variables are set if you perform conditional compilation.
|
||||
#[serde(alias = "before-build-command")]
|
||||
pub before_build_command: Option<String>,
|
||||
pub before_build_command: Option<BeforeBuildCommand>,
|
||||
/// Features passed to `cargo` commands.
|
||||
pub features: Option<Vec<String>>,
|
||||
/// Whether we should inject the Tauri API on `window.__TAURI__` or not.
|
||||
|
@ -2449,16 +2449,24 @@
|
||||
},
|
||||
"beforeDevCommand": {
|
||||
"description": "A shell command to run before `tauri dev` kicks in.\n\nThe TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG environment variables are set if you perform conditional compilation.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/BeforeDevCommand"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"beforeBuildCommand": {
|
||||
"description": "A shell command to run before `tauri build` kicks in.\n\nThe TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG environment variables are set if you perform conditional compilation.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/BeforeBuildCommand"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"features": {
|
||||
@ -2499,6 +2507,69 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"BeforeDevCommand": {
|
||||
"description": "Describes the shell command to run before `tauri dev`.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Run the given script with the default options.",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "Run the given script with custom options.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"script"
|
||||
],
|
||||
"properties": {
|
||||
"script": {
|
||||
"description": "The script to execute.",
|
||||
"type": "string"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The current working directory.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"wait": {
|
||||
"description": "Whether `tauri dev` should wait for the command to finish or not. Defaults to `false`.",
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"BeforeBuildCommand": {
|
||||
"description": "Describes the shell command to run before `tauri build`.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Run the given script with the default options.",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "Run the given script with custom options.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"script"
|
||||
],
|
||||
"properties": {
|
||||
"script": {
|
||||
"description": "The script to execute.",
|
||||
"type": "string"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The current working directory.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"PluginConfig": {
|
||||
"description": "The plugin configs holds a HashMap mapping a plugin name to its configuration object.",
|
||||
"type": "object",
|
||||
|
@ -6,7 +6,9 @@ use crate::{
|
||||
helpers::{
|
||||
app_paths::{app_dir, tauri_dir},
|
||||
command_env,
|
||||
config::{get as get_config, AppUrl, WindowUrl, MERGE_CONFIG_EXTENSION_NAME},
|
||||
config::{
|
||||
get as get_config, AppUrl, BeforeBuildCommand, WindowUrl, MERGE_CONFIG_EXTENSION_NAME,
|
||||
},
|
||||
updater_signature::{read_key_from_file, secret_key as updater_secret_key, sign_file},
|
||||
},
|
||||
interface::{AppInterface, AppSettings, Interface},
|
||||
@ -112,23 +114,29 @@ pub fn command(mut options: Options) -> Result<()> {
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
if let Some(before_build) = &config_.build.before_build_command {
|
||||
if !before_build.is_empty() {
|
||||
if let Some(before_build) = config_.build.before_build_command.clone() {
|
||||
let (script, script_cwd) = match before_build {
|
||||
BeforeBuildCommand::Script(s) if s.is_empty() => (None, None),
|
||||
BeforeBuildCommand::Script(s) => (Some(s), None),
|
||||
BeforeBuildCommand::ScriptWithOptions { script, cwd } => (Some(script), cwd.map(Into::into)),
|
||||
};
|
||||
let cwd = script_cwd.unwrap_or_else(|| app_dir().clone());
|
||||
if let Some(before_build) = script {
|
||||
info!(action = "Running"; "beforeBuildCommand `{}`", before_build);
|
||||
#[cfg(target_os = "windows")]
|
||||
let status = Command::new("cmd")
|
||||
.arg("/S")
|
||||
.arg("/C")
|
||||
.arg(before_build)
|
||||
.current_dir(app_dir())
|
||||
.arg(&before_build)
|
||||
.current_dir(cwd)
|
||||
.envs(command_env(options.debug))
|
||||
.piped()
|
||||
.with_context(|| format!("failed to run `{}` with `cmd /C`", before_build))?;
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let status = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(before_build)
|
||||
.current_dir(app_dir())
|
||||
.arg(&before_build)
|
||||
.current_dir(cwd)
|
||||
.envs(command_env(options.debug))
|
||||
.piped()
|
||||
.with_context(|| format!("failed to run `{}` with `sh -c`", before_build))?;
|
||||
|
@ -6,14 +6,14 @@ use crate::{
|
||||
helpers::{
|
||||
app_paths::{app_dir, tauri_dir},
|
||||
command_env,
|
||||
config::{get as get_config, AppUrl, WindowUrl},
|
||||
config::{get as get_config, AppUrl, BeforeDevCommand, WindowUrl},
|
||||
},
|
||||
interface::{AppInterface, ExitReason, Interface},
|
||||
Result,
|
||||
CommandExt, Result,
|
||||
};
|
||||
use clap::Parser;
|
||||
|
||||
use anyhow::Context;
|
||||
use anyhow::{bail, Context};
|
||||
use log::{error, info, warn};
|
||||
use once_cell::sync::OnceCell;
|
||||
use shared_child::SharedChild;
|
||||
@ -89,65 +89,92 @@ fn command_internal(mut options: Options) -> Result<()> {
|
||||
|
||||
let config = get_config(options.config.as_deref())?;
|
||||
|
||||
if let Some(before_dev) = &config
|
||||
if let Some(before_dev) = config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.build
|
||||
.before_dev_command
|
||||
.clone()
|
||||
{
|
||||
if !before_dev.is_empty() {
|
||||
let (script, script_cwd, wait) = match before_dev {
|
||||
BeforeDevCommand::Script(s) if s.is_empty() => (None, None, false),
|
||||
BeforeDevCommand::Script(s) => (Some(s), None, false),
|
||||
BeforeDevCommand::ScriptWithOptions { script, cwd, wait } => {
|
||||
(Some(script), cwd.map(Into::into), wait)
|
||||
}
|
||||
};
|
||||
let cwd = script_cwd.unwrap_or_else(|| app_dir().clone());
|
||||
if let Some(before_dev) = script {
|
||||
info!(action = "Running"; "BeforeDevCommand (`{}`)", before_dev);
|
||||
#[cfg(target_os = "windows")]
|
||||
#[cfg(windows)]
|
||||
let mut command = {
|
||||
let mut command = Command::new("cmd");
|
||||
command
|
||||
.arg("/S")
|
||||
.arg("/C")
|
||||
.arg(before_dev)
|
||||
.current_dir(app_dir())
|
||||
.arg(&before_dev)
|
||||
.current_dir(cwd)
|
||||
.envs(command_env(true));
|
||||
command
|
||||
};
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[cfg(not(windows))]
|
||||
let mut command = {
|
||||
let mut command = Command::new("sh");
|
||||
command
|
||||
.arg("-c")
|
||||
.arg(before_dev)
|
||||
.current_dir(app_dir())
|
||||
.arg(&before_dev)
|
||||
.current_dir(cwd)
|
||||
.envs(command_env(true));
|
||||
command
|
||||
};
|
||||
command.stdin(Stdio::piped());
|
||||
command.stdout(os_pipe::dup_stdout()?);
|
||||
command.stderr(os_pipe::dup_stderr()?);
|
||||
|
||||
let child = SharedChild::spawn(&mut command)
|
||||
.unwrap_or_else(|_| panic!("failed to run `{}`", before_dev));
|
||||
let child = Arc::new(child);
|
||||
let child_ = child.clone();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let status = child_
|
||||
.wait()
|
||||
.expect("failed to wait on \"beforeDevCommand\"");
|
||||
if !(status.success() || KILL_BEFORE_DEV_FLAG.get().unwrap().load(Ordering::Relaxed)) {
|
||||
error!("The \"beforeDevCommand\" terminated with a non-zero status code.");
|
||||
exit(status.code().unwrap_or(1));
|
||||
if wait {
|
||||
let status = command.piped().with_context(|| {
|
||||
format!(
|
||||
"failed to run `{}` with `{}`",
|
||||
before_dev,
|
||||
if cfg!(windows) { "cmd /S /C" } else { "sh -c" }
|
||||
)
|
||||
})?;
|
||||
if !status.success() {
|
||||
bail!(
|
||||
"beforeDevCommand `{}` failed with exit code {}",
|
||||
before_dev,
|
||||
status.code().unwrap_or_default()
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
command.stdin(Stdio::piped());
|
||||
command.stdout(os_pipe::dup_stdout()?);
|
||||
command.stderr(os_pipe::dup_stderr()?);
|
||||
|
||||
BEFORE_DEV.set(Mutex::new(child)).unwrap();
|
||||
KILL_BEFORE_DEV_FLAG.set(AtomicBool::default()).unwrap();
|
||||
let child = SharedChild::spawn(&mut command)
|
||||
.unwrap_or_else(|_| panic!("failed to run `{}`", before_dev));
|
||||
let child = Arc::new(child);
|
||||
let child_ = child.clone();
|
||||
|
||||
let _ = ctrlc::set_handler(move || {
|
||||
kill_before_dev_process();
|
||||
#[cfg(not(debug_assertions))]
|
||||
let _ = check_for_updates();
|
||||
exit(130);
|
||||
});
|
||||
std::thread::spawn(move || {
|
||||
let status = child_
|
||||
.wait()
|
||||
.expect("failed to wait on \"beforeDevCommand\"");
|
||||
if !(status.success() || KILL_BEFORE_DEV_FLAG.get().unwrap().load(Ordering::Relaxed)) {
|
||||
error!("The \"beforeDevCommand\" terminated with a non-zero status code.");
|
||||
exit(status.code().unwrap_or(1));
|
||||
}
|
||||
});
|
||||
|
||||
BEFORE_DEV.set(Mutex::new(child)).unwrap();
|
||||
KILL_BEFORE_DEV_FLAG.set(AtomicBool::default()).unwrap();
|
||||
|
||||
let _ = ctrlc::set_handler(move || {
|
||||
kill_before_dev_process();
|
||||
#[cfg(not(debug_assertions))]
|
||||
let _ = check_for_updates();
|
||||
exit(130);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user