mirror of
https://github.com/velopack/velopack.git
synced 2025-10-25 15:19:22 +00:00
Fix up legacy migrations
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
use crate::{
|
||||
shared::{self, OperationWait},
|
||||
};
|
||||
use velopack::{bundle::load_bundle_from_file, bundle::Manifest, locator::VelopackLocator, constants};
|
||||
use crate::shared::{self, OperationWait};
|
||||
use velopack::{locator::VelopackLocator, constants};
|
||||
use anyhow::{bail, Result};
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -19,13 +17,14 @@ pub fn apply<'a>(
|
||||
package: Option<&PathBuf>,
|
||||
exe_args: Option<Vec<&str>>,
|
||||
run_hooks: bool,
|
||||
) -> Result<()> {
|
||||
) -> Result<VelopackLocator> {
|
||||
shared::operation_wait(wait);
|
||||
|
||||
let package = package.cloned().map_or_else(|| auto_locate_package(&locator), Ok);
|
||||
|
||||
let packages_dir = locator.get_packages_dir();
|
||||
let package = package.cloned().or_else(|| shared::find_latest_full_package(&packages_dir).map(|x| x.0));
|
||||
|
||||
match package {
|
||||
Ok(package) => {
|
||||
Some(package) => {
|
||||
info!("Getting ready to apply package to {} ver {}: {}",
|
||||
locator.get_manifest_id(),
|
||||
locator.get_manifest_version_full_string(),
|
||||
@@ -37,15 +36,15 @@ pub fn apply<'a>(
|
||||
if restart {
|
||||
shared::start_package(&applied_locator, exe_args, Some(constants::HOOK_ENV_RESTART))?;
|
||||
}
|
||||
return Ok(());
|
||||
return Ok(applied_locator);
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Error applying package: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to locate package ({}).", e);
|
||||
None => {
|
||||
error!("Failed to locate full package to apply. Please provide with the --package {{path}} argument");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,33 +55,3 @@ pub fn apply<'a>(
|
||||
|
||||
bail!("Apply failed, see logs for details.");
|
||||
}
|
||||
|
||||
fn auto_locate_package(locator: &VelopackLocator) -> Result<PathBuf> {
|
||||
let packages_dir = locator.get_packages_dir_as_string();
|
||||
info!("Attempting to auto-detect package in: {}", packages_dir);
|
||||
let mut package_path: Option<PathBuf> = None;
|
||||
let mut package_manifest: Option<Manifest> = None;
|
||||
|
||||
if let Ok(paths) = glob::glob(format!("{}/*.nupkg", packages_dir).as_str()) {
|
||||
for path in paths {
|
||||
if let Ok(path) = path {
|
||||
trace!("Checking package: '{}'", path.to_string_lossy());
|
||||
if let Ok(mut bun) = load_bundle_from_file(&path) {
|
||||
if let Ok(mani) = bun.read_manifest() {
|
||||
if package_manifest.is_none() || mani.version > package_manifest.clone().unwrap().version {
|
||||
info!("Found {}: '{}'", mani.version, path.to_string_lossy());
|
||||
package_manifest = Some(mani);
|
||||
package_path = Some(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(p) = package_path {
|
||||
Ok(p)
|
||||
} else {
|
||||
bail!("Unable to find/load suitable package. Provide via the --package argument.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
use crate::shared::{self, OperationWait};
|
||||
use anyhow::Result;
|
||||
use velopack::locator::VelopackLocator;
|
||||
|
||||
#[allow(unused_variables, unused_imports)]
|
||||
pub fn start(
|
||||
locator: &VelopackLocator,
|
||||
wait: OperationWait,
|
||||
exe_name: Option<&String>,
|
||||
exe_args: Option<Vec<&str>>,
|
||||
@@ -20,10 +18,14 @@ pub fn start(
|
||||
shared::operation_wait(wait);
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
super::start_windows_impl::start_impl(&locator, exe_name, exe_args, legacy_args)?;
|
||||
super::start_windows_impl::start_impl(exe_name, exe_args, legacy_args)?;
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
shared::start_package(&locator, exe_args, None)?;
|
||||
{
|
||||
use velopack::locator::{auto_locate_app_manifest, LocationContext};
|
||||
let locator = auto_locate_app_manifest(LocationContext::IAmUpdateExe)?;
|
||||
shared::start_package(&locator, exe_args, None)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -8,63 +8,122 @@ use std::os::windows::process::CommandExt;
|
||||
use std::{
|
||||
fs,
|
||||
path::Path,
|
||||
path::PathBuf,
|
||||
process::Command as Process,
|
||||
};
|
||||
use velopack::{bundle, constants};
|
||||
use velopack::locator::VelopackLocator;
|
||||
use velopack::{bundle::Manifest, constants};
|
||||
use velopack::locator::{auto_locate_app_manifest, create_config_from_root_dir, LocationContext, VelopackLocator};
|
||||
use windows::Win32::UI::WindowsAndMessaging::AllowSetForegroundWindow;
|
||||
|
||||
pub fn start_impl(
|
||||
locator: &VelopackLocator,
|
||||
exe_name: Option<&String>,
|
||||
exe_args: Option<Vec<&str>>,
|
||||
legacy_args: Option<&String>,
|
||||
) -> Result<()> {
|
||||
let root_dir = locator.get_root_dir();
|
||||
let app_title = locator.get_manifest_title();
|
||||
match shared::has_app_prefixed_folder(&root_dir) {
|
||||
Ok(has_prefix) => {
|
||||
if has_prefix {
|
||||
info!("This is a legacy app. Will try and upgrade it now.");
|
||||
enum LocatorResult
|
||||
{
|
||||
Normal(VelopackLocator),
|
||||
Legacy(PathBuf, Manifest),
|
||||
}
|
||||
|
||||
// if started by legacy Squirrel, the working dir of Update.exe may be inside the app-* folder,
|
||||
// meaning we can not clean up properly.
|
||||
std::env::set_current_dir(&root_dir)?;
|
||||
|
||||
return match try_legacy_migration(&locator) {
|
||||
Ok(new_locator) => {
|
||||
shared::start_package(&new_locator, exe_args, Some(constants::HOOK_ENV_RESTART))?;
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Failed to migrate legacy app ({}).", e);
|
||||
dialogs::show_error(
|
||||
&app_title,
|
||||
Some("Unable to start app"),
|
||||
"This app installation has been corrupted and cannot be started. Please reinstall the app.",
|
||||
);
|
||||
Err(e)
|
||||
impl LocatorResult {
|
||||
pub fn get_root_dir(&self) -> PathBuf {
|
||||
match self {
|
||||
LocatorResult::Normal(locator) => locator.get_root_dir(),
|
||||
LocatorResult::Legacy(path, _) => path.clone(),
|
||||
}
|
||||
}
|
||||
pub fn get_manifest(&self) -> Manifest {
|
||||
match self {
|
||||
LocatorResult::Normal(locator) => locator.get_manifest(),
|
||||
LocatorResult::Legacy(_, manifest) => manifest.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_current_dir(&self) -> PathBuf {
|
||||
match self {
|
||||
LocatorResult::Normal(locator) => locator.get_current_bin_dir(),
|
||||
LocatorResult::Legacy(path, _) => path.join("current"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_exe_to_start(&self, name: Option<&String>) -> Result<PathBuf> {
|
||||
let current_dir = self.get_current_dir();
|
||||
if let Some(name) = name {
|
||||
Ok(Path::new(¤t_dir).join(name))
|
||||
} else {
|
||||
match self {
|
||||
LocatorResult::Normal(locator) => Ok(locator.get_main_exe_path()),
|
||||
LocatorResult::Legacy(_, manifest) => {
|
||||
if manifest.main_exe.is_empty() {
|
||||
bail!("No main exe specified in manifest and exe name argument was not provided.");
|
||||
} else {
|
||||
Ok(Path::new(¤t_dir).join(&manifest.main_exe))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => warn!("Failed legacy check ({}).", e),
|
||||
}
|
||||
}
|
||||
|
||||
fn legacy_locator() -> Result<LocatorResult> {
|
||||
let locator = auto_locate_app_manifest(LocationContext::IAmUpdateExe);
|
||||
match locator {
|
||||
Ok(locator) => Ok(LocatorResult::Normal(locator)),
|
||||
Err(e) => {
|
||||
warn!("Failed to locate app manifest ({}), trying legacy package resolution...", e);
|
||||
let my_exe = std::env::current_exe()?;
|
||||
let parent_dir = my_exe.parent().expect("Unable to determine parent directory");
|
||||
let packages_dir = parent_dir.join("packages");
|
||||
if let Some((path, manifest)) = shared::find_latest_full_package(&packages_dir) {
|
||||
info!("Found full package to read: {}", path.to_string_lossy());
|
||||
Ok(LocatorResult::Legacy(path, manifest))
|
||||
} else {
|
||||
bail!("Unable to locate app manifest or full package in {}.", packages_dir.to_string_lossy());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_impl(
|
||||
exe_name: Option<&String>,
|
||||
exe_args: Option<Vec<&str>>,
|
||||
legacy_args: Option<&String>,
|
||||
) -> Result<()> {
|
||||
let locator = legacy_locator()?;
|
||||
let root_dir = locator.get_root_dir();
|
||||
let manifest = locator.get_manifest();
|
||||
if shared::has_app_prefixed_folder(&root_dir) {
|
||||
match try_legacy_migration(&root_dir, &manifest) {
|
||||
Ok(new_locator) => {
|
||||
shared::start_package(&new_locator, exe_args, Some(constants::HOOK_ENV_RESTART))?;
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Failed to migrate legacy app ({}).", e);
|
||||
dialogs::show_error(
|
||||
&manifest.title,
|
||||
Some("Unable to start app"),
|
||||
"This app installation has been corrupted and cannot be started. Please re-install the app.",
|
||||
);
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
start_regular(locator, exe_name, exe_args, legacy_args)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn start_regular(
|
||||
locator: LocatorResult,
|
||||
exe_name: Option<&String>,
|
||||
exe_args: Option<Vec<&str>>,
|
||||
legacy_args: Option<&String>,
|
||||
) -> Result<()> {
|
||||
// we can't just run the normal start_package command, because legacy squirrel might provide
|
||||
// an "exe name" to restart which no longer exists in the package
|
||||
|
||||
let current = locator.get_current_bin_dir();
|
||||
let exe_to_execute = if let Some(exe) = exe_name {
|
||||
Path::new(¤t).join(exe)
|
||||
} else {
|
||||
locator.get_main_exe_path()
|
||||
};
|
||||
|
||||
let exe_to_execute = locator.get_exe_to_start(exe_name)?;
|
||||
if !exe_to_execute.exists() {
|
||||
bail!("Unable to find executable to start: '{:?}'", exe_to_execute);
|
||||
}
|
||||
|
||||
|
||||
let current = locator.get_current_dir();
|
||||
info!("About to launch: '{:?}' in dir '{:?}'", exe_to_execute, current);
|
||||
|
||||
let mut cmd = Process::new(&exe_to_execute);
|
||||
@@ -81,15 +140,22 @@ pub fn start_impl(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn try_legacy_migration(locator: &VelopackLocator) -> Result<VelopackLocator> {
|
||||
let root_dir = locator.get_root_dir();
|
||||
let current_dir = locator.get_current_bin_dir();
|
||||
let package = shared::find_latest_full_package(&locator).ok_or_else(|| anyhow!("Unable to find latest full package."))?;
|
||||
let mut bundle = bundle::load_bundle_from_file(&package.file_path)?;
|
||||
let bundle_manifest = bundle.read_manifest()?; // this verifies it's a bundle we support
|
||||
fn try_legacy_migration(root_dir: &PathBuf, manifest: &Manifest) -> Result<VelopackLocator> {
|
||||
info!("This is a legacy app. Will try and upgrade it now.");
|
||||
|
||||
// if started by legacy Squirrel, the working dir of Update.exe may be inside the app-* folder,
|
||||
// meaning we can not clean up properly.
|
||||
std::env::set_current_dir(&root_dir)?;
|
||||
|
||||
let _mutex = shared::retry_io(|| crate::windows::create_global_mutex(&manifest.id))?;
|
||||
let path_config = create_config_from_root_dir(root_dir);
|
||||
|
||||
let package = shared::find_latest_full_package(&path_config.PackagesDir).ok_or_else(|| anyhow!("Unable to find latest full package."))?;
|
||||
|
||||
warn!("This application is installed in a folder prefixed with 'app-'. Attempting to migrate...");
|
||||
let _ = shared::force_stop_package(&root_dir);
|
||||
|
||||
let current_dir = &path_config.CurrentBinaryDir;
|
||||
if !Path::new(¤t_dir).exists() {
|
||||
info!("Renaming latest app-* folder to current.");
|
||||
if let Some((latest_app_dir, _latest_ver)) = shared::get_latest_app_version_folder(&root_dir)? {
|
||||
@@ -102,16 +168,16 @@ fn try_legacy_migration(locator: &VelopackLocator) -> Result<VelopackLocator> {
|
||||
|
||||
// reset current manifest shortcuts, so when the new manifest is being read
|
||||
// new shortcuts will be force-created
|
||||
let modified_app = locator.clone_self_with_blank_shortcuts();
|
||||
let mut modified_manifest = manifest.clone();
|
||||
modified_manifest.shortcut_locations = String::new();
|
||||
|
||||
info!("Applying latest full package...");
|
||||
let buf = Path::new(&package.file_path).to_path_buf();
|
||||
super::apply(&modified_app, false, OperationWait::NoWait, Some(&buf), None, false)?;
|
||||
let buf = Path::new(&package.0).to_path_buf();
|
||||
let locator = VelopackLocator::new(path_config, modified_manifest);
|
||||
let new_locator = super::apply(&locator, false, OperationWait::NoWait, Some(&buf), None, false)?;
|
||||
|
||||
info!("Removing old app-* folders...");
|
||||
shared::delete_app_prefixed_folders(&root_dir)?;
|
||||
let _ = remove_dir_all::remove_dir_all(root_dir.join("staging"));
|
||||
|
||||
let new_locator = locator.clone_self_with_new_manifest(&bundle_manifest);
|
||||
Ok(new_locator)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ use anyhow::{anyhow, Result};
|
||||
use rand::distributions::{Alphanumeric, DistString};
|
||||
use regex::Regex;
|
||||
use std::{path::Path, thread, time::Duration};
|
||||
use std::path::PathBuf;
|
||||
use velopack::bundle::{load_bundle_from_file, Manifest};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum OperationWait {
|
||||
@@ -24,6 +26,30 @@ pub fn operation_wait(wait: OperationWait) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_latest_full_package(packages_dir: &PathBuf) -> Option<(PathBuf, Manifest)> {
|
||||
let packages_dir = packages_dir.to_string_lossy();
|
||||
|
||||
info!("Attempting to auto-detect package in: {}", packages_dir);
|
||||
let mut package: Option<(PathBuf, Manifest)> = None;
|
||||
|
||||
if let Ok(paths) = glob::glob(format!("{}/*.nupkg", packages_dir).as_str()) {
|
||||
for path in paths {
|
||||
if let Ok(path) = path {
|
||||
trace!("Checking package: '{}'", path.to_string_lossy());
|
||||
if let Ok(mut bun) = load_bundle_from_file(&path) {
|
||||
if let Ok(mani) = bun.read_manifest() {
|
||||
if package.is_none() || mani.version > package.clone().unwrap().1.version {
|
||||
info!("Found {}: '{}'", mani.version, path.to_string_lossy());
|
||||
package = Some((path, mani));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
package
|
||||
}
|
||||
|
||||
pub fn retry_io<F, T, E>(op: F) -> Result<T, E>
|
||||
where
|
||||
F: Fn() -> Result<T, E>,
|
||||
|
||||
@@ -13,7 +13,6 @@ use windows::Wdk::System::Threading::{NtQueryInformationProcess, ProcessBasicInf
|
||||
use windows::Win32::System::Threading::{GetCurrentProcess, PROCESS_BASIC_INFORMATION};
|
||||
use winsafe::{self as w, co, prelude::*};
|
||||
|
||||
use velopack::bundle::{self, EntryNameInfo};
|
||||
use velopack::locator::VelopackLocator;
|
||||
|
||||
pub fn wait_for_pid_to_exit(pid: u32, ms_to_wait: u32) -> Result<()> {
|
||||
@@ -246,8 +245,14 @@ pub fn get_latest_app_version_folder<P: AsRef<Path>>(parent_path: P) -> Result<O
|
||||
Ok(latest_folder.zip(latest_version))
|
||||
}
|
||||
|
||||
pub fn has_app_prefixed_folder<P: AsRef<Path>>(parent_path: P) -> Result<bool> {
|
||||
Ok(!get_app_prefixed_folders(parent_path)?.is_empty())
|
||||
pub fn has_app_prefixed_folder<P: AsRef<Path>>(parent_path: P) -> bool {
|
||||
match get_app_prefixed_folders(parent_path) {
|
||||
Ok(folders) => !folders.is_empty(),
|
||||
Err(e) => {
|
||||
warn!("Failed to check for app-prefixed folders: {}", e);
|
||||
false
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete_app_prefixed_folders<P: AsRef<Path>>(parent_path: P) -> Result<()> {
|
||||
@@ -262,71 +267,6 @@ fn parse_version_from_folder_name(folder_name: &str) -> Option<Version> {
|
||||
folder_name.strip_prefix("app-").and_then(|v| Version::parse(v).ok())
|
||||
}
|
||||
|
||||
// fn find_manifest_from_root_dir(root_path: &PathBuf) -> Result<Manifest> {
|
||||
// // default to checking current/sq.version
|
||||
// let cm = find_current_manifest(root_path);
|
||||
// if cm.is_ok() {
|
||||
// return cm;
|
||||
// }
|
||||
//
|
||||
// // if that fails, check for latest full package
|
||||
// warn!("Unable to find current manifest, checking for latest full package. (LEGACY MODE)");
|
||||
// let latest = find_latest_full_package(root_path);
|
||||
// if let Some(latest) = latest {
|
||||
// let mani = latest.load_manifest()?;
|
||||
// return Ok(mani);
|
||||
// }
|
||||
//
|
||||
// bail!("Unable to locate manifest or package.");
|
||||
// }
|
||||
//
|
||||
// fn find_current_manifest(root_path: &PathBuf) -> Result<Manifest> {
|
||||
// let m = Manifest::default();
|
||||
// let nuspec_path = m.get_nuspec_path(root_path);
|
||||
// if Path::new(&nuspec_path).exists() {
|
||||
// if let Ok(nuspec) = super::retry_io(|| std::fs::read_to_string(&nuspec_path)) {
|
||||
// return Ok(bundle::read_manifest_from_string(&nuspec)?);
|
||||
// }
|
||||
// }
|
||||
// bail!("Unable to read nuspec file in current directory.")
|
||||
// }
|
||||
|
||||
pub fn find_latest_full_package(locator: &VelopackLocator) -> Option<EntryNameInfo> {
|
||||
let packages = get_all_packages(locator);
|
||||
let mut latest: Option<EntryNameInfo> = None;
|
||||
for pkg in packages {
|
||||
if pkg.is_delta {
|
||||
continue;
|
||||
}
|
||||
if latest.is_none() {
|
||||
latest = Some(pkg);
|
||||
} else {
|
||||
let latest_ver = latest.clone().unwrap().version;
|
||||
if pkg.version > latest_ver {
|
||||
latest = Some(pkg);
|
||||
}
|
||||
}
|
||||
}
|
||||
latest
|
||||
}
|
||||
|
||||
fn get_all_packages(locator: &VelopackLocator) -> Vec<EntryNameInfo> {
|
||||
let packages = locator.get_packages_dir();
|
||||
let mut vec = Vec::new();
|
||||
debug!("Scanning for packages in {:?}", packages);
|
||||
if let Ok(entries) = fs::read_dir(packages) {
|
||||
for entry in entries {
|
||||
if let Ok(entry) = entry {
|
||||
if let Some(pkg) = bundle::parse_package_file_path(entry.path()) {
|
||||
debug!("Found package: {}", entry.path().to_string_lossy());
|
||||
vec.push(pkg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
vec
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_running_processes_finds_cargo() {
|
||||
let profile = crate::windows::known_path::get_user_profile().unwrap();
|
||||
|
||||
@@ -63,7 +63,7 @@ fn root_command() -> Command {
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn parse_command_line_matches(input_args: Vec<String>) -> ArgMatches {
|
||||
fn try_parse_command_line_matches(input_args: Vec<String>) -> Result<ArgMatches> {
|
||||
// Split the arguments manually to handle the legacy `--flag=value` syntax
|
||||
// Also, replace `--processStartAndWait` with `--processStart --wait`
|
||||
let mut args = Vec::new();
|
||||
@@ -93,7 +93,7 @@ fn parse_command_line_matches(input_args: Vec<String>) -> ArgMatches {
|
||||
args.push(arg);
|
||||
}
|
||||
}
|
||||
root_command().get_matches_from(&args)
|
||||
Ok(root_command().try_get_matches_from(&args)?)
|
||||
}
|
||||
|
||||
fn get_flag_or_false(matches: &ArgMatches, id: &str) -> bool {
|
||||
@@ -118,9 +118,9 @@ fn main() -> Result<()> {
|
||||
windows::mitigate::pre_main_sideload_mitigation();
|
||||
|
||||
#[cfg(windows)]
|
||||
let matches = parse_command_line_matches(env::args().collect());
|
||||
let matches = try_parse_command_line_matches(env::args().collect())?;
|
||||
#[cfg(unix)]
|
||||
let matches = root_command().get_matches();
|
||||
let matches = root_command().try_get_matches()?;
|
||||
|
||||
let (subcommand, subcommand_matches) = matches.subcommand().ok_or_else(|| anyhow!("No subcommand was used. Try `--help` for more information."))?;
|
||||
|
||||
@@ -131,7 +131,7 @@ fn main() -> Result<()> {
|
||||
dialogs::set_silent(silent);
|
||||
let desired_log_file = log_file.cloned().unwrap_or(locator::default_log_location(LocationContext::IAmUpdateExe));
|
||||
logging::setup_logging("update", Some(&desired_log_file), true, verbose)?;
|
||||
|
||||
|
||||
// change working directory to the parent directory of the exe
|
||||
let mut containing_dir = env::current_exe()?;
|
||||
containing_dir.pop();
|
||||
@@ -191,7 +191,8 @@ fn apply(matches: &ArgMatches) -> Result<()> {
|
||||
let locator = auto_locate_app_manifest(LocationContext::IAmUpdateExe)?;
|
||||
#[cfg(target_os = "windows")]
|
||||
let _mutex = shared::retry_io(|| windows::create_global_mutex(&locator.get_manifest_id()))?;
|
||||
commands::apply(&locator, restart, wait, package, exe_args, true)
|
||||
let _ = commands::apply(&locator, restart, wait, package, exe_args, true)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn start(matches: &ArgMatches) -> Result<()> {
|
||||
@@ -208,11 +209,8 @@ fn start(matches: &ArgMatches) -> Result<()> {
|
||||
info!(" Legacy Args: {:?}", legacy_args);
|
||||
warn!("Legacy args format is deprecated and will be removed in a future release. Please update your application to use the new format.");
|
||||
}
|
||||
|
||||
let locator = auto_locate_app_manifest(LocationContext::IAmUpdateExe)?;
|
||||
#[cfg(target_os = "windows")]
|
||||
let _mutex = shared::retry_io(|| windows::create_global_mutex(&locator.get_manifest_id()))?;
|
||||
commands::start(&locator, wait, exe_name, exe_args, legacy_args)
|
||||
|
||||
commands::start(wait, exe_name, exe_args, legacy_args)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
@@ -230,40 +228,7 @@ fn test_start_command_supports_legacy_commands() {
|
||||
let wait_for_parent = get_flag_or_false(&matches, "wait");
|
||||
let exe_name = matches.get_one::<String>("EXE_NAME");
|
||||
let exe_args: Option<Vec<&String>> = matches.get_many::<String>("EXE_ARGS").map(|v| v.collect());
|
||||
return (wait_for_parent, exe_name, legacy_args, exe_args);
|
||||
}
|
||||
|
||||
fn try_parse_command_line_matches(input_args: Vec<String>) -> Result<ArgMatches> {
|
||||
// Split the arguments manually to handle the legacy `--flag=value` syntax
|
||||
// Also, replace `--processStartAndWait` with `--processStart --wait`
|
||||
let mut args = Vec::new();
|
||||
let mut preserve = false;
|
||||
for arg in input_args {
|
||||
if preserve {
|
||||
args.push(arg);
|
||||
} else if arg == "--" {
|
||||
args.push("--".to_string());
|
||||
preserve = true;
|
||||
} else if arg.eq_ignore_ascii_case("--processStartAndWait") {
|
||||
args.push("--processStart".to_string());
|
||||
args.push("--wait".to_string());
|
||||
} else if arg.starts_with("--processStartAndWait=") {
|
||||
let mut split_arg = arg.splitn(2, '=');
|
||||
split_arg.next(); // Skip the `--processStartAndWait` part
|
||||
args.push("--processStart".to_string());
|
||||
args.push("--wait".to_string());
|
||||
if let Some(rest) = split_arg.next() {
|
||||
args.push(rest.to_string());
|
||||
}
|
||||
} else if arg.contains('=') {
|
||||
let mut split_arg = arg.splitn(2, '=');
|
||||
args.push(split_arg.next().unwrap().to_string());
|
||||
args.push(split_arg.next().unwrap().to_string());
|
||||
} else {
|
||||
args.push(arg);
|
||||
}
|
||||
}
|
||||
root_command().try_get_matches_from(&args).map_err(|e| anyhow!("{}", e))
|
||||
(wait_for_parent, exe_name, legacy_args, exe_args)
|
||||
}
|
||||
|
||||
let command = vec!["Update.exe", "--processStart=hello.exe"];
|
||||
|
||||
Reference in New Issue
Block a user