mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-04-03 10:11:15 +02:00
289 lines
8.1 KiB
Rust
289 lines
8.1 KiB
Rust
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
#![allow(
|
|
// Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422
|
|
clippy::nonstandard_macro_braces,
|
|
)]
|
|
|
|
pub use anyhow::Result;
|
|
use clap::{crate_version, load_yaml, App, AppSettings, ArgMatches};
|
|
use dialoguer::Input;
|
|
use serde::Deserialize;
|
|
|
|
mod build;
|
|
mod dev;
|
|
mod helpers;
|
|
mod info;
|
|
mod init;
|
|
mod interface;
|
|
mod sign;
|
|
|
|
// temporary fork from https://github.com/mitsuhiko/console until 0.14.1+ release
|
|
#[allow(dead_code)]
|
|
mod console;
|
|
// temporary fork from https://github.com/mitsuhiko/dialoguer until 0.8.0+ release
|
|
#[allow(dead_code)]
|
|
mod dialoguer;
|
|
|
|
use helpers::framework::{infer_from_package_json as infer_framework, Framework};
|
|
|
|
use std::{env::current_dir, fs::read_to_string, path::PathBuf};
|
|
|
|
#[derive(Deserialize)]
|
|
struct PackageJson {
|
|
name: Option<String>,
|
|
product_name: Option<String>,
|
|
}
|
|
|
|
#[derive(Default)]
|
|
struct InitDefaults {
|
|
app_name: Option<String>,
|
|
framework: Option<Framework>,
|
|
}
|
|
|
|
macro_rules! value_or_prompt {
|
|
($init_runner: ident, $setter_fn: ident, $value: ident, $ci: ident, $prompt_message: expr, $prompt_default: expr) => {{
|
|
let mut init_runner = $init_runner;
|
|
if let Some(value) = $value {
|
|
init_runner = init_runner.$setter_fn(value);
|
|
} else if !$ci {
|
|
let mut builder = Input::<String>::new();
|
|
builder.with_prompt($prompt_message);
|
|
if let Some(default) = $prompt_default {
|
|
builder.default(default);
|
|
}
|
|
let input = builder.interact_text()?;
|
|
init_runner = init_runner.$setter_fn(input);
|
|
}
|
|
init_runner
|
|
}};
|
|
}
|
|
|
|
fn init_command(matches: &ArgMatches) -> Result<()> {
|
|
let force = matches.is_present("force");
|
|
let directory = matches.value_of("directory");
|
|
let tauri_path = matches.value_of("tauri-path");
|
|
let app_name = matches.value_of("app-name");
|
|
let window_title = matches.value_of("window-title");
|
|
let dist_dir = matches.value_of("dist-dir");
|
|
let dev_path = matches.value_of("dev-path");
|
|
let ci = matches.is_present("ci") || std::env::var("CI").is_ok();
|
|
|
|
let mut init_runner = init::Init::new();
|
|
if force {
|
|
init_runner = init_runner.force();
|
|
}
|
|
let base_directory = if let Some(directory) = directory {
|
|
init_runner = init_runner.directory(directory);
|
|
PathBuf::from(directory)
|
|
} else {
|
|
current_dir().expect("failed to read cwd")
|
|
};
|
|
if let Some(tauri_path) = tauri_path {
|
|
init_runner = init_runner.tauri_path(tauri_path);
|
|
}
|
|
|
|
let package_json_path = base_directory.join("package.json");
|
|
let init_defaults = if package_json_path.exists() {
|
|
let package_json_text = read_to_string(package_json_path)?;
|
|
let package_json: PackageJson = serde_json::from_str(&package_json_text)?;
|
|
let (framework, _) = infer_framework(&package_json_text);
|
|
InitDefaults {
|
|
app_name: package_json.product_name.or(package_json.name),
|
|
framework,
|
|
}
|
|
} else {
|
|
Default::default()
|
|
};
|
|
|
|
init_runner = value_or_prompt!(
|
|
init_runner,
|
|
app_name,
|
|
app_name,
|
|
ci,
|
|
"What is your app name?",
|
|
init_defaults.app_name.clone()
|
|
);
|
|
init_runner = value_or_prompt!(
|
|
init_runner,
|
|
window_title,
|
|
window_title,
|
|
ci,
|
|
"What should the window title be?",
|
|
init_defaults.app_name.clone()
|
|
);
|
|
init_runner = value_or_prompt!(
|
|
init_runner,
|
|
dist_dir,
|
|
dist_dir,
|
|
ci,
|
|
r#"Where are your web assets (HTML/CSS/JS) located, relative to the "<current dir>/src-tauri" folder that will be created?"#,
|
|
init_defaults.framework.as_ref().map(|f| f.dist_dir())
|
|
);
|
|
init_runner = value_or_prompt!(
|
|
init_runner,
|
|
dev_path,
|
|
dev_path,
|
|
ci,
|
|
"What is the url of your dev server?",
|
|
init_defaults.framework.map(|f| f.dev_path())
|
|
);
|
|
|
|
init_runner.run()
|
|
}
|
|
|
|
fn dev_command(matches: &ArgMatches) -> Result<()> {
|
|
let runner = matches.value_of("runner");
|
|
let target = matches.value_of("target");
|
|
let features: Vec<String> = matches
|
|
.values_of("features")
|
|
.map(|a| a.into_iter().map(|v| v.to_string()).collect())
|
|
.unwrap_or_default();
|
|
let exit_on_panic = matches.is_present("exit-on-panic");
|
|
let config = matches.value_of("config");
|
|
let args: Vec<String> = matches
|
|
.values_of("args")
|
|
.map(|a| a.into_iter().map(|v| v.to_string()).collect())
|
|
.unwrap_or_default();
|
|
|
|
let mut dev_runner = dev::Dev::new()
|
|
.exit_on_panic(exit_on_panic)
|
|
.args(args)
|
|
.features(features);
|
|
|
|
if let Some(runner) = runner {
|
|
dev_runner = dev_runner.runner(runner.to_string());
|
|
}
|
|
if let Some(target) = target {
|
|
dev_runner = dev_runner.target(target.to_string());
|
|
}
|
|
if let Some(config) = config {
|
|
dev_runner = dev_runner.config(config.to_string());
|
|
}
|
|
|
|
dev_runner.run()
|
|
}
|
|
|
|
fn build_command(matches: &ArgMatches) -> Result<()> {
|
|
let runner = matches.value_of("runner");
|
|
let target = matches.value_of("target");
|
|
let features: Vec<String> = matches
|
|
.values_of("features")
|
|
.map(|a| a.into_iter().map(|v| v.to_string()).collect())
|
|
.unwrap_or_default();
|
|
let debug = matches.is_present("debug");
|
|
let verbose = matches.is_present("verbose");
|
|
let bundles = matches.values_of_lossy("bundle");
|
|
let config = matches.value_of("config");
|
|
|
|
let mut build_runner = build::Build::new().features(features);
|
|
if let Some(runner) = runner {
|
|
build_runner = build_runner.runner(runner.to_string());
|
|
}
|
|
if let Some(target) = target {
|
|
build_runner = build_runner.target(target.to_string());
|
|
}
|
|
if debug {
|
|
build_runner = build_runner.debug();
|
|
}
|
|
if verbose {
|
|
build_runner = build_runner.verbose();
|
|
}
|
|
if let Some(bundles) = bundles {
|
|
build_runner = build_runner.bundles(bundles);
|
|
}
|
|
if let Some(config) = config {
|
|
build_runner = build_runner.config(config.to_string());
|
|
}
|
|
|
|
build_runner.run()
|
|
}
|
|
|
|
fn info_command() -> Result<()> {
|
|
info::Info::new().run()
|
|
}
|
|
|
|
fn sign_command(matches: &ArgMatches) -> Result<()> {
|
|
let private_key = matches.value_of("private-key");
|
|
let private_key_path = matches.value_of("private-key-path");
|
|
let file = matches.value_of("sign-file");
|
|
let password = matches.value_of("password");
|
|
let no_password = matches.is_present("no-password");
|
|
let write_keys = matches.value_of("write-keys");
|
|
let force = matches.is_present("force");
|
|
|
|
// generate keypair
|
|
if matches.is_present("generate") {
|
|
let mut keygen_runner = sign::KeyGenerator::new();
|
|
|
|
if no_password {
|
|
keygen_runner = keygen_runner.empty_password();
|
|
}
|
|
|
|
if force {
|
|
keygen_runner = keygen_runner.force();
|
|
}
|
|
|
|
if let Some(write_keys) = write_keys {
|
|
keygen_runner = keygen_runner.output_path(write_keys);
|
|
}
|
|
|
|
if let Some(password) = password {
|
|
keygen_runner = keygen_runner.password(password);
|
|
}
|
|
|
|
return keygen_runner.generate_keys();
|
|
}
|
|
|
|
// sign our binary / archive
|
|
let mut sign_runner = sign::Signer::new();
|
|
if let Some(private_key) = private_key {
|
|
sign_runner = sign_runner.private_key(private_key);
|
|
}
|
|
|
|
if let Some(private_key_path) = private_key_path {
|
|
sign_runner = sign_runner.private_key_path(private_key_path);
|
|
}
|
|
|
|
if let Some(file) = file {
|
|
sign_runner = sign_runner.file_to_sign(file);
|
|
}
|
|
|
|
if let Some(password) = password {
|
|
sign_runner = sign_runner.password(password);
|
|
}
|
|
|
|
if no_password {
|
|
sign_runner = sign_runner.empty_password();
|
|
}
|
|
|
|
sign_runner.run()
|
|
}
|
|
|
|
fn main() -> Result<()> {
|
|
let yaml = load_yaml!("cli.yml");
|
|
let app = App::from(yaml)
|
|
.version(crate_version!())
|
|
.setting(AppSettings::ArgRequiredElseHelp)
|
|
.setting(AppSettings::GlobalVersion)
|
|
.setting(AppSettings::SubcommandRequired);
|
|
let app_matches = app.get_matches();
|
|
let matches = app_matches.subcommand_matches("tauri").unwrap();
|
|
|
|
if let Some(matches) = matches.subcommand_matches("init") {
|
|
init_command(matches)?;
|
|
} else if let Some(matches) = matches.subcommand_matches("dev") {
|
|
dev_command(matches)?;
|
|
} else if let Some(matches) = matches.subcommand_matches("build") {
|
|
build_command(matches)?;
|
|
} else if matches.subcommand_matches("info").is_some() {
|
|
info_command()?;
|
|
} else if let Some(matches) = matches.subcommand_matches("sign") {
|
|
sign_command(matches)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|