Skip to main content

cargo_truce/
lib.rs

1//! `cargo-truce` library - engine for `cargo truce <subcommand>`.
2//!
3//! `main.rs` owns argument parsing, the `cargo truce` arg strip,
4//! the user-facing help block, and dispatch for `new` (single +
5//! `--workspace` modes, which live in the [`scaffold`] module).
6//! Every other subcommand goes through [`run`].
7
8mod commands;
9mod config;
10pub(crate) mod dirs;
11mod error;
12mod format;
13mod install_scope;
14pub(crate) mod preset_codec;
15pub mod scaffold;
16mod templates;
17mod util;
18
19pub use error::CargoTruceError;
20
21// The Windows packager + its DPI/icon manifest helper now live under
22// `commands::package::{windows, windows_manifest}` (alongside the
23// macOS / Linux packagers), so they no longer need a crate-root `mod`
24// or a `PkgFormat` re-export - `windows.rs` reaches `super::PkgFormat`
25// like its siblings.
26
27// Crate-root re-export of the AAX template builder, used by the
28// Windows packager. Cfg-gated so it isn't dead on macOS / Linux.
29#[cfg(target_os = "windows")]
30pub(crate) use commands::install::aax::build_aax_template;
31#[cfg(target_os = "macos")]
32pub(crate) use config::installer_identity;
33pub(crate) use config::{
34    Config, PluginDef, application_identity, deployment_target, load_config, read_build_env,
35    resolve_aax_sdk_path,
36};
37#[cfg(target_os = "macos")]
38pub(crate) use config::{
39    ios_appex_provisioning_profile, ios_application_identity, ios_provisioning_profile, ios_team_id,
40};
41#[cfg(any(target_os = "macos", test))]
42pub(crate) use util::tmp_verify;
43pub(crate) use util::{
44    cargo_build, cargo_build_debug, check_cmd, codesign_bundle, confirm_prompt,
45    detect_default_features, find_on_path, is_debug_profile, log_output, log_skip, project_root,
46    read_standalone_bin_name, release_lib, set_build_profile, set_debug_profile, set_target_cpu,
47    tag_fail, tag_ok, tag_warn, take_outputs, take_skipped, verify_shell_profile_declared,
48    vprintln,
49};
50// `run_sudo` shells out to `/usr/bin/sudo`, which only exists on macOS in
51// our supported targets. Windows admin elevation is per-process (UAC, not
52// per-command) and Linux installs are always per-user, so the helper has
53// no meaningful implementation off macOS - the cfg gate forces callers to
54// stay platform-aware rather than silently spawning a missing binary.
55#[cfg(target_os = "macos")]
56pub(crate) use util::run_sudo;
57// `tmp_dir` is the raw escape hatch - used by `reset_au` (macOS only)
58// to walk every subdir under `tmp/`. Most callers pick the typed
59// helper that matches their purpose (`tmp_manifests`, `tmp_lv2`, …).
60#[cfg(target_os = "macos")]
61pub(crate) use util::tmp_dir;
62// `tmp_manifests` is used on both macOS (codesign / AU / VST plist
63// scratch) and Windows (Azure signing metadata). Not used on Linux
64// since the tarball pipeline doesn't shell out to platform tools.
65#[cfg(any(target_os = "macos", target_os = "windows"))]
66pub(crate) use util::tmp_manifests;
67// `tmp_lv2` is consumed only by `install_lv2`'s macOS sudo-stage
68// path - Windows/Linux installers write straight into the destination
69// without staging, since neither needs the per-command privilege
70// escalation that drives the macOS detour.
71#[cfg(target_os = "macos")]
72pub(crate) use util::tmp_lv2;
73
74// `read_workspace_version` is consumed by all three packagers
75// (macOS / Windows / Linux tarball), so it stays unconditional.
76pub(crate) use util::read_workspace_version;
77
78// `release_lib_for_target` resolves a per-triple build output path; it
79// powers macOS universal lipo, Windows x64+arm64, and Linux dual-arch
80// `--target` builds. Always available.
81pub(crate) use util::release_lib_for_target;
82#[cfg(target_os = "macos")]
83pub(crate) use util::{release_bundle_bin, release_static_for_target};
84
85// `tag_info` formats the doctor/packager status prefix; the `doctor`
86// command runs on every platform, so this stays unconditional.
87pub(crate) use util::tag_info;
88
89// Re-exports used only by the macOS / Windows installer pipelines.
90// Linux ships plugins via distro tooling rather than the bundled
91// `package` flow, so these symbols are absent there.
92#[cfg(any(target_os = "macos", target_os = "windows"))]
93pub(crate) use util::{rustup_has_target, tmp_aax_template};
94
95// macOS-only: codesign / lipo / notary / AAX PACE-sign pipeline. The
96// `MacosPackagingConfig` / `copy_dir_recursive` re-exports land here
97// too - only `commands::package::{macos, stage}` consume them, and
98// both are macOS-gated.
99#[cfg(target_os = "macos")]
100pub(crate) use config::MacosPackagingConfig;
101#[cfg(target_os = "macos")]
102pub(crate) use util::{
103    CLAP_EXPORTS, MacArch, VST2_EXPORTS, VST3_EXPORTS, cargo_build_for_arch,
104    cargo_build_multi_arch, copy_dir_recursive, extract_team_id, is_production_identity,
105    link_macos_bundle, lipo_into, locate_wraptool_macos, missing_staticlib_error,
106    pace_sign_aax_macos, run_codesign, run_silent, tmp_au_v3,
107};
108
109// Windows-only: VS / MSVC / cmake / ninja discovery + Program Files
110// path helpers, used by `commands::{doctor, install, install::aax}`
111// and `commands::package::windows`.
112#[cfg(target_os = "windows")]
113pub(crate) use util::{
114    cargo_rustc_bin, common_program_files, locate_cmake, locate_msvc_cl, locate_ninja,
115    locate_vcvars64, locate_vcvarsall, program_files, tmp_scripts, vs_install_paths, which_exe,
116};
117
118use std::process::ExitCode;
119
120pub type Res = std::result::Result<(), CargoTruceError>;
121
122/// Run a command with the given args (e.g. `["install", "--clap"]`).
123///
124/// Help, scaffold (`new`), and the `cargo truce`
125/// arg-stripping live in `main.rs`. Unknown commands here surface
126/// back to the caller as an error so `main` can render its own help
127/// block.
128#[must_use]
129pub fn run(args: &[String]) -> ExitCode {
130    // Strip global `-v` / `--verbose` from anywhere in the arg list.
131    // Setting the static once here means every subcommand picks it up
132    // without each having to parse the flag.
133    let mut filtered: Vec<String> = Vec::with_capacity(args.len());
134    for a in args {
135        if a == "-v" || a == "--verbose" {
136            util::set_verbose(true);
137        } else {
138            filtered.push(a.clone());
139        }
140    }
141    let args = &filtered[..];
142
143    let cmd = args.first().map_or("", std::string::String::as_str);
144
145    let result = match cmd {
146        "install" => commands::install::cmd_install(&args[1..]),
147        "build" => commands::build::cmd_build(&args[1..]),
148        "package" => commands::package::cmd_package(&args[1..]),
149        "uninstall" => commands::uninstall::cmd_uninstall(&args[1..]),
150        "run" => commands::run::cmd_run(&args[1..]),
151        "screenshot" => commands::screenshot::cmd_screenshot(&args[1..]),
152        "status" => commands::status::cmd_status(&args[1..]),
153        "reset-au" => commands::reset_au::cmd_reset_au(&args[1..]),
154        "reset-aax" => commands::reset_aax::cmd_reset_aax(&args[1..]),
155        "validate" => commands::validate::cmd_validate(&args[1..]),
156        "preset" => commands::preset::cmd_preset(&args[1..]),
157        "doctor" => commands::doctor::cmd_doctor(&args[1..]),
158        "log-stream-au" => commands::log_stream_au::cmd_log_stream_au(&args[1..]),
159        other => Err(format!("unknown command: {other:?}").into()),
160    };
161
162    match result {
163        Ok(()) => ExitCode::SUCCESS,
164        Err(e) => {
165            eprintln!("Error: {e}");
166            ExitCode::FAILURE
167        }
168    }
169}