mirror of
				https://github.com/velopack/velopack.git
				synced 2025-10-25 15:19:22 +00:00 
			
		
		
		
	Remove logging callbacks from C++ / NodeJS
This commit is contained in:
		
							
								
								
									
										4
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -2190,10 +2190,12 @@ dependencies = [ | |||||||
|  "async-std", |  "async-std", | ||||||
|  "bitflags 2.9.0", |  "bitflags 2.9.0", | ||||||
|  "derivative", |  "derivative", | ||||||
|  |  "file-rotate", | ||||||
|  "glob", |  "glob", | ||||||
|  "lazy_static", |  "lazy_static", | ||||||
|  "libc", |  "libc", | ||||||
|  "log", |  "log", | ||||||
|  |  "log-panics", | ||||||
|  "normpath", |  "normpath", | ||||||
|  "rand", |  "rand", | ||||||
|  "regex", |  "regex", | ||||||
| @@ -2202,8 +2204,10 @@ dependencies = [ | |||||||
|  "serde_json", |  "serde_json", | ||||||
|  "sha1", |  "sha1", | ||||||
|  "sha2", |  "sha2", | ||||||
|  |  "simplelog", | ||||||
|  "tempfile", |  "tempfile", | ||||||
|  "thiserror 2.0.12", |  "thiserror 2.0.12", | ||||||
|  |  "time 0.3.37", | ||||||
|  "ts-rs", |  "ts-rs", | ||||||
|  "ureq", |  "ureq", | ||||||
|  "url", |  "url", | ||||||
|   | |||||||
| @@ -23,7 +23,7 @@ edition = "2021" | |||||||
| rust-version = "1.75" | rust-version = "1.75" | ||||||
|  |  | ||||||
| [workspace.dependencies] | [workspace.dependencies] | ||||||
| velopack = { path = "src/lib-rust" } | velopack = { path = "src/lib-rust", features = ["file-logging"] } | ||||||
| log = "0.4" | log = "0.4" | ||||||
| log-derive = "0.4.1" | log-derive = "0.4.1" | ||||||
| ureq = "3.0" | ureq = "3.0" | ||||||
|   | |||||||
| @@ -116,7 +116,7 @@ pub fn install(pkg: &mut BundleZip, install_to: Option<&PathBuf>, start_args: Op | |||||||
|      |      | ||||||
|     info!("Acquiring lock..."); |     info!("Acquiring lock..."); | ||||||
|     let paths = create_config_from_root_dir(&root_path); |     let paths = create_config_from_root_dir(&root_path); | ||||||
|     let locator = VelopackLocator::new(paths, app); |     let locator = VelopackLocator::new_with_manifest(paths, app); | ||||||
|     let _mutex = locator.try_get_exclusive_lock()?; |     let _mutex = locator.try_get_exclusive_lock()?; | ||||||
|  |  | ||||||
|     let tx = if dialogs::get_silent() { |     let tx = if dialogs::get_silent() { | ||||||
|   | |||||||
| @@ -156,7 +156,7 @@ fn try_legacy_migration(root_dir: &PathBuf, manifest: &Manifest) -> Result<Velop | |||||||
|     // new shortcuts will be force-created |     // new shortcuts will be force-created | ||||||
|     let mut modified_manifest = manifest.clone(); |     let mut modified_manifest = manifest.clone(); | ||||||
|     modified_manifest.shortcut_locations = String::new(); |     modified_manifest.shortcut_locations = String::new(); | ||||||
|     let locator = VelopackLocator::new(path_config, modified_manifest); |     let locator = VelopackLocator::new_with_manifest(path_config, modified_manifest); | ||||||
|     let _mutex = locator.try_get_exclusive_lock()?; |     let _mutex = locator.try_get_exclusive_lock()?; | ||||||
|  |  | ||||||
|     if !locator.get_current_bin_dir().exists() { |     if !locator.get_current_bin_dir().exists() { | ||||||
|   | |||||||
| @@ -1,5 +1,4 @@ | |||||||
| pub mod commands; | pub mod commands; | ||||||
| pub mod logging; |  | ||||||
| pub mod shared; | pub mod shared; | ||||||
| #[cfg(target_os = "windows")] | #[cfg(target_os = "windows")] | ||||||
| pub mod windows; | pub mod windows; | ||||||
| @@ -8,6 +7,5 @@ pub use shared::dialogs; | |||||||
|  |  | ||||||
| #[macro_use] | #[macro_use] | ||||||
| extern crate log; | extern crate log; | ||||||
| extern crate simplelog; |  | ||||||
| #[macro_use] | #[macro_use] | ||||||
| extern crate lazy_static; | extern crate lazy_static; | ||||||
|   | |||||||
| @@ -1,58 +0,0 @@ | |||||||
| use anyhow::Result; |  | ||||||
| use simplelog::*; |  | ||||||
| use std::path::PathBuf; |  | ||||||
| use time::format_description::{modifier, Component, FormatItem}; |  | ||||||
|  |  | ||||||
| pub fn trace_logger() { |  | ||||||
|     TermLogger::init(LevelFilter::Trace, get_config(None), TerminalMode::Mixed, ColorChoice::Never).unwrap(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| pub fn setup_logging(process_name: &str, file: Option<&PathBuf>, console: bool, verbose: bool) -> Result<()> { |  | ||||||
|     let mut loggers: Vec<Box<dyn SharedLogger>> = Vec::new(); |  | ||||||
|     let color_choice = ColorChoice::Never; |  | ||||||
|     if console { |  | ||||||
|         let console_level = if verbose { LevelFilter::Debug } else { LevelFilter::Info }; |  | ||||||
|         loggers.push(TermLogger::new(console_level, get_config(None), TerminalMode::Mixed, color_choice)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if let Some(f) = file { |  | ||||||
|         let file_level = if verbose { LevelFilter::Trace } else { LevelFilter::Info }; |  | ||||||
|         let writer = file_rotate::FileRotate::new( |  | ||||||
|             f.clone(), |  | ||||||
|             file_rotate::suffix::AppendCount::new(1),          // keep 1 old log file |  | ||||||
|             file_rotate::ContentLimit::Bytes(1 * 1024 * 1024), // 1MB max log file size |  | ||||||
|             file_rotate::compression::Compression::None, |  | ||||||
|             None, |  | ||||||
|         ); |  | ||||||
|         loggers.push(WriteLogger::new(file_level, get_config(Some(process_name)), writer)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     CombinedLogger::init(loggers)?; |  | ||||||
|     log_panics::init(); |  | ||||||
|     Ok(()) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| fn get_config(process_name: Option<&str>) -> Config { |  | ||||||
|     let mut c = ConfigBuilder::default(); |  | ||||||
|     let mut prefix = "".to_owned(); |  | ||||||
|     if let Some(pn) = process_name { |  | ||||||
|         prefix = format!("[{}:{}] ", pn, std::process::id()); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     let prefix_heaped = Box::leak(prefix.into_boxed_str()); |  | ||||||
|  |  | ||||||
|     let time_format: &'static [FormatItem<'static>] = Box::leak(Box::new([ |  | ||||||
|         FormatItem::Literal(prefix_heaped.as_bytes()), |  | ||||||
|         FormatItem::Literal(b"["), |  | ||||||
|         FormatItem::Component(Component::Hour(modifier::Hour::default())), |  | ||||||
|         FormatItem::Literal(b":"), |  | ||||||
|         FormatItem::Component(Component::Minute(modifier::Minute::default())), |  | ||||||
|         FormatItem::Literal(b":"), |  | ||||||
|         FormatItem::Component(Component::Second(modifier::Second::default())), |  | ||||||
|         FormatItem::Literal(b"]"), |  | ||||||
|     ])); |  | ||||||
|  |  | ||||||
|     c.set_time_format_custom(time_format); |  | ||||||
|     let _ = c.set_time_offset_to_local(); // might fail if local tz can't be determined |  | ||||||
|     c.build() |  | ||||||
| } |  | ||||||
| @@ -79,7 +79,7 @@ fn main_inner() -> Result<()> { | |||||||
|  |  | ||||||
|     let verbose = matches.get_flag("verbose"); |     let verbose = matches.get_flag("verbose"); | ||||||
|     let logfile = matches.get_one::<PathBuf>("log"); |     let logfile = matches.get_one::<PathBuf>("log"); | ||||||
|     logging::setup_logging("setup", logfile, true, verbose)?; |     velopack::logging::init_logging("setup", logfile, true, verbose); | ||||||
|  |  | ||||||
|     let debug = matches.get_one::<PathBuf>("debug"); |     let debug = matches.get_one::<PathBuf>("debug"); | ||||||
|     let install_to = matches.get_one::<PathBuf>("installto"); |     let install_to = matches.get_one::<PathBuf>("installto"); | ||||||
|   | |||||||
| @@ -1,8 +1,6 @@ | |||||||
| #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] | #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] | ||||||
| #![allow(dead_code)] | #![allow(dead_code)] | ||||||
|  |  | ||||||
| mod logging; |  | ||||||
|  |  | ||||||
| #[macro_use] | #[macro_use] | ||||||
| extern crate log; | extern crate log; | ||||||
|  |  | ||||||
| @@ -21,7 +19,7 @@ fn main() -> ExitCode { | |||||||
|         my_dir.join("Velopack.log") |         my_dir.join("Velopack.log") | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     let _ = logging::setup_logging("stub", Some(&default_log_file), false, false); |     let _ = velopack::logging::init_logging("stub", Some(&default_log_file), false, false); | ||||||
|  |  | ||||||
|     info!("--"); |     info!("--"); | ||||||
|     info!("Starting Velopack Stub (at {:?})", my_path); |     info!("Starting Velopack Stub (at {:?})", my_path); | ||||||
|   | |||||||
| @@ -7,8 +7,9 @@ extern crate log; | |||||||
| use anyhow::{anyhow, bail, Result}; | use anyhow::{anyhow, bail, Result}; | ||||||
| use clap::{arg, value_parser, ArgMatches, Command}; | use clap::{arg, value_parser, ArgMatches, Command}; | ||||||
| use std::{env, path::PathBuf}; | use std::{env, path::PathBuf}; | ||||||
| use velopack::locator::{self, auto_locate_app_manifest, LocationContext}; | use velopack::locator::{auto_locate_app_manifest, LocationContext}; | ||||||
| use velopack_bins::{*, shared::OperationWait}; | use velopack::logging::*; | ||||||
|  | use velopack_bins::{shared::OperationWait, *}; | ||||||
|  |  | ||||||
| #[rustfmt::skip] | #[rustfmt::skip] | ||||||
| fn root_command() -> Command { | fn root_command() -> Command { | ||||||
| @@ -132,8 +133,8 @@ fn main() -> Result<()> { | |||||||
|  |  | ||||||
|     let verbose = get_flag_or_false(&matches, "verbose"); |     let verbose = get_flag_or_false(&matches, "verbose"); | ||||||
|     let log_file = matches.get_one("log"); |     let log_file = matches.get_one("log"); | ||||||
|     let desired_log_file = log_file.cloned().unwrap_or(locator::default_log_location(LocationContext::IAmUpdateExe)); |     let desired_log_file = log_file.cloned().unwrap_or(default_logfile_from_context(LocationContext::IAmUpdateExe)); | ||||||
|     logging::setup_logging("update", Some(&desired_log_file), true, verbose)?; |     init_logging("update", Some(&desired_log_file), true, verbose); | ||||||
|  |  | ||||||
|     // change working directory to the parent directory of the exe |     // change working directory to the parent directory of the exe | ||||||
|     let mut containing_dir = env::current_exe()?; |     let mut containing_dir = env::current_exe()?; | ||||||
| @@ -212,7 +213,6 @@ fn apply(matches: &ArgMatches) -> Result<()> { | |||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| fn get_start_args(matches: &ArgMatches) -> (OperationWait, Option<&String>, Option<&String>, Option<Vec<&str>>) { | fn get_start_args(matches: &ArgMatches) -> (OperationWait, Option<&String>, Option<&String>, Option<Vec<&str>>) { | ||||||
|     let legacy_args = matches.get_one::<String>("args"); |     let legacy_args = matches.get_one::<String>("args"); | ||||||
|     let exe_name = matches.get_one::<String>("EXE_NAME"); |     let exe_name = matches.get_one::<String>("EXE_NAME"); | ||||||
| @@ -246,10 +246,10 @@ fn uninstall(_matches: &ArgMatches) -> Result<()> { | |||||||
| #[cfg(target_os = "windows")] | #[cfg(target_os = "windows")] | ||||||
| #[test] | #[test] | ||||||
| fn test_cli_parse_handles_equals_spaces() { | fn test_cli_parse_handles_equals_spaces() { | ||||||
|     let command = vec!["C:\\Some Path\\With = Spaces\\Update.exe", "apply" , "--package", "C:\\Some Path\\With = Spaces\\Package.zip"]; |     let command = vec!["C:\\Some Path\\With = Spaces\\Update.exe", "apply", "--package", "C:\\Some Path\\With = Spaces\\Package.zip"]; | ||||||
|     let matches = try_parse_command_line_matches(command.iter().map(|s| s.to_string()).collect()).unwrap(); |     let matches = try_parse_command_line_matches(command.iter().map(|s| s.to_string()).collect()).unwrap(); | ||||||
|     let (wait, restart, package, exe_args) = get_apply_args(matches.subcommand_matches("apply").unwrap()); |     let (wait, restart, package, exe_args) = get_apply_args(matches.subcommand_matches("apply").unwrap()); | ||||||
|      |  | ||||||
|     assert_eq!(wait, OperationWait::NoWait); |     assert_eq!(wait, OperationWait::NoWait); | ||||||
|     assert_eq!(restart, true); |     assert_eq!(restart, true); | ||||||
|     assert_eq!(package, Some(&PathBuf::from("C:\\Some Path\\With = Spaces\\Package.zip"))); |     assert_eq!(package, Some(&PathBuf::from("C:\\Some Path\\With = Spaces\\Package.zip"))); | ||||||
|   | |||||||
| @@ -179,13 +179,6 @@ typedef void (*vpkc_progress_callback_t)(void *p_user_data, size_t progress); | |||||||
|  */ |  */ | ||||||
| typedef void (*vpkc_hook_callback_t)(void *p_user_data, const char *psz_app_version); | typedef void (*vpkc_hook_callback_t)(void *p_user_data, const char *psz_app_version); | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Log callback function. |  | ||||||
|  */ |  | ||||||
| typedef void (*vpkc_log_callback_t)(void *p_user_data, |  | ||||||
|                                     const char *psz_level, |  | ||||||
|                                     const char *psz_message); |  | ||||||
|  |  | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| #endif // __cplusplus | #endif // __cplusplus | ||||||
| @@ -399,12 +392,6 @@ void vpkc_app_set_hook_restarted(vpkc_hook_callback_t cb_restarted); | |||||||
|  */ |  */ | ||||||
| size_t vpkc_get_last_error(char *psz_error, size_t c_error); | size_t vpkc_get_last_error(char *psz_error, size_t c_error); | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Set a custom log callback. This will be called for all log messages generated by the Velopack library. |  | ||||||
|  */ |  | ||||||
| void vpkc_set_logger(vpkc_log_callback_t cb_log, |  | ||||||
|                      void *p_user_data); |  | ||||||
|  |  | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| }  // extern "C" | }  // extern "C" | ||||||
| #endif  // __cplusplus | #endif  // __cplusplus | ||||||
|   | |||||||
| @@ -16,6 +16,8 @@ use libc::{c_char, c_void, size_t}; | |||||||
| use log_derive::{logfn, logfn_inputs}; | use log_derive::{logfn, logfn_inputs}; | ||||||
| use std::{ffi::CString, ptr}; | use std::{ffi::CString, ptr}; | ||||||
| use velopack::{sources, ApplyWaitMode, Error as VelopackError, UpdateCheck, UpdateManager, VelopackApp}; | use velopack::{sources, ApplyWaitMode, Error as VelopackError, UpdateCheck, UpdateManager, VelopackApp}; | ||||||
|  | use velopack::locator::{LocationContext}; | ||||||
|  | use velopack::logging::{default_logfile_from_config, default_logfile_from_context, init_logging}; | ||||||
|  |  | ||||||
| /// Create a new FileSource update source for a given file path. | /// Create a new FileSource update source for a given file path. | ||||||
| #[no_mangle] | #[no_mangle] | ||||||
| @@ -437,7 +439,15 @@ pub extern "C" fn vpkc_app_run(p_user_data: *mut c_void) { | |||||||
|             hook(p_user_data, c_string.as_ptr()); |             hook(p_user_data, c_string.as_ptr()); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  |      | ||||||
|  |     // init logging | ||||||
|  |     let log_file = if let Some(locator) = &app_options.locator { | ||||||
|  |         default_logfile_from_config(locator) | ||||||
|  |     } else { | ||||||
|  |         default_logfile_from_context(LocationContext::FromCurrentExe) | ||||||
|  |     }; | ||||||
|  |      | ||||||
|  |     init_logging("lib-cpp", Some(&log_file), false, false); | ||||||
|     app.run(); |     app.run(); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -530,10 +540,4 @@ pub extern "C" fn vpkc_app_set_hook_restarted(cb_restarted: vpkc_hook_callback_t | |||||||
| pub extern "C" fn vpkc_get_last_error(psz_error: *mut c_char, c_error: size_t) -> size_t { | pub extern "C" fn vpkc_get_last_error(psz_error: *mut c_char, c_error: size_t) -> size_t { | ||||||
|     let error = get_last_error(); |     let error = get_last_error(); | ||||||
|     return_cstr(psz_error, c_error, &error) |     return_cstr(psz_error, c_error, &error) | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Set a custom log callback. This will be called for all log messages generated by the Velopack library. |  | ||||||
| #[no_mangle] |  | ||||||
| pub extern "C" fn vpkc_set_logger(cb_log: vpkc_log_callback_t, p_user_data: *mut c_void) { |  | ||||||
|     set_log_callback(cb_log, p_user_data); |  | ||||||
| } |  | ||||||
| @@ -1,7 +1,5 @@ | |||||||
| use anyhow::Result; | use anyhow::Result; | ||||||
| use log::{Level, Log, Metadata, Record}; | use std::sync::RwLock; | ||||||
| use std::ffi::{c_void, CString}; |  | ||||||
| use std::sync::{Mutex, RwLock}; |  | ||||||
| use velopack::locator::VelopackLocatorConfig; | use velopack::locator::VelopackLocatorConfig; | ||||||
|  |  | ||||||
| use crate::types::*; | use crate::types::*; | ||||||
| @@ -21,7 +19,6 @@ pub struct AppOptions { | |||||||
|  |  | ||||||
| lazy_static::lazy_static! { | lazy_static::lazy_static! { | ||||||
|     static ref LAST_ERROR: RwLock<String> = RwLock::new(String::new()); |     static ref LAST_ERROR: RwLock<String> = RwLock::new(String::new()); | ||||||
|     static ref LOG_CALLBACK: Mutex<(vpkc_log_callback_t, usize)> = Mutex::new((None, 0)); |  | ||||||
|     pub static ref VELOPACK_APP: RwLock<AppOptions> = RwLock::new(Default::default()); |     pub static ref VELOPACK_APP: RwLock<AppOptions> = RwLock::new(Default::default()); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -64,53 +61,3 @@ where | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| pub fn set_log_callback(callback: vpkc_log_callback_t, user_data: *mut c_void) { |  | ||||||
|     // Initialize the logger if it hasn't been set yet |  | ||||||
|     let _ = log::set_logger(&LOGGER); |  | ||||||
|     log::set_max_level(log::LevelFilter::Trace); |  | ||||||
|  |  | ||||||
|     let mut log_callback = LOG_CALLBACK.lock().unwrap(); |  | ||||||
|     *log_callback = (callback, user_data as usize); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| pub fn log_message(level: &str, message: &str) { |  | ||||||
|     let log_callback = LOG_CALLBACK.lock().unwrap(); |  | ||||||
|     let (callback, user_data) = *log_callback; |  | ||||||
|     if let Some(callback) = callback { |  | ||||||
|         let c_level = CString::new(level).unwrap(); |  | ||||||
|         let c_message = CString::new(message).unwrap(); |  | ||||||
|         callback(user_data as *mut c_void, c_level.as_ptr(), c_message.as_ptr()); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| struct LoggerImpl {} |  | ||||||
|  |  | ||||||
| static LOGGER: LoggerImpl = LoggerImpl {}; |  | ||||||
|  |  | ||||||
| impl Log for LoggerImpl { |  | ||||||
|     fn enabled(&self, metadata: &Metadata) -> bool { |  | ||||||
|         metadata.level() <= log::max_level() |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     fn log(&self, record: &Record) { |  | ||||||
|         if !self.enabled(record.metadata()) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         let text = format!("{}", record.args()); |  | ||||||
|  |  | ||||||
|         let level = match record.level() { |  | ||||||
|             Level::Error => "error", |  | ||||||
|             Level::Warn => "warn", |  | ||||||
|             Level::Info => "info", |  | ||||||
|             Level::Debug => "debug", |  | ||||||
|             Level::Trace => "trace", |  | ||||||
|         } |  | ||||||
|         .to_string(); |  | ||||||
|  |  | ||||||
|         log_message(&level, &text); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     fn flush(&self) {} |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -22,9 +22,6 @@ pub type vpkc_update_source_t = c_void; | |||||||
| /// Progress callback function. | /// Progress callback function. | ||||||
| pub type vpkc_progress_callback_t = Option<extern "C" fn(p_user_data: *mut c_void, progress: size_t)>; | pub type vpkc_progress_callback_t = Option<extern "C" fn(p_user_data: *mut c_void, progress: size_t)>; | ||||||
|  |  | ||||||
| /// Log callback function. |  | ||||||
| pub type vpkc_log_callback_t = Option<extern "C" fn(p_user_data: *mut c_void, psz_level: *const c_char, psz_message: *const c_char)>; |  | ||||||
|  |  | ||||||
| /// VelopackApp startup hook callback function. | /// VelopackApp startup hook callback function. | ||||||
| pub type vpkc_hook_callback_t = Option<extern "C" fn(p_user_data: *mut c_void, psz_app_version: *const c_char)>; | pub type vpkc_hook_callback_t = Option<extern "C" fn(p_user_data: *mut c_void, psz_app_version: *const c_char)>; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -47,10 +47,6 @@ declare module "./load" { | |||||||
|     locator: string | null, |     locator: string | null, | ||||||
|     autoApply: boolean, |     autoApply: boolean, | ||||||
|   ): void; |   ): void; | ||||||
|  |  | ||||||
|   function js_set_logger_callback( |  | ||||||
|     cb: (loglevel: LogLevel, msg: string) => void, |  | ||||||
|   ): void; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| type VelopackHookType = | type VelopackHookType = | ||||||
| @@ -63,8 +59,6 @@ type VelopackHookType = | |||||||
|  |  | ||||||
| type VelopackHook = (version: string) => void; | type VelopackHook = (version: string) => void; | ||||||
|  |  | ||||||
| type LogLevel = "info" | "warn" | "error" | "debug" | "trace"; |  | ||||||
|  |  | ||||||
| /**  | /**  | ||||||
|  * VelopackApp helps you to handle app activation events correctly. |  * VelopackApp helps you to handle app activation events correctly. | ||||||
|  * This should be used as early as possible in your application startup code. |  * This should be used as early as possible in your application startup code. | ||||||
| @@ -300,13 +294,4 @@ export class UpdateManager { | |||||||
|       restartArgs, |       restartArgs, | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Set a custom logger callback to receive log messages from Velopack. The default behavior is to log to console.log. |  | ||||||
|  */ |  | ||||||
| export function setVelopackLogger( |  | ||||||
|   callback: (loglevel: LogLevel, msg: string) => void, |  | ||||||
| ) { |  | ||||||
|   addon.js_set_logger_callback(callback); |  | ||||||
| } |  | ||||||
| @@ -7,8 +7,7 @@ use std::sync::{Arc, Mutex}; | |||||||
| use std::thread; | use std::thread; | ||||||
| use velopack::sources::*; | use velopack::sources::*; | ||||||
| use velopack::*; | use velopack::*; | ||||||
|  | use velopack::logging::{default_logfile_from_config, default_logfile_from_context}; | ||||||
| mod logger; |  | ||||||
|  |  | ||||||
| struct UpdateManagerWrapper { | struct UpdateManagerWrapper { | ||||||
|     manager: UpdateManager, |     manager: UpdateManager, | ||||||
| @@ -262,30 +261,29 @@ fn js_appbuilder_run(mut cx: FunctionContext) -> JsResult<JsUndefined> { | |||||||
|             .on_after_update_fast_callback(|semver| hook_handler("after-update", semver)); |             .on_after_update_fast_callback(|semver| hook_handler("after-update", semver)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if let Some(locator) = locator { |     if let Some(locator) = &locator { | ||||||
|         builder = builder.set_locator(locator); |         builder = builder.set_locator(locator.clone()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if let Some(arg_array) = argarray { |     if let Some(arg_array) = argarray { | ||||||
|         builder = builder.set_args(arg_array); |         builder = builder.set_args(arg_array); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // init logging | ||||||
|  |     let log_file = if let Some(locator) = &locator { | ||||||
|  |         default_logfile_from_config(locator) | ||||||
|  |     } else { | ||||||
|  |         default_logfile_from_context(LocationContext::FromCurrentExe) | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     logging::init_logging("lib-nodejs", Some(&log_file), false, false); | ||||||
|     builder.run(); |     builder.run(); | ||||||
|  |  | ||||||
|     Ok(undefined) |     Ok(undefined) | ||||||
| } | } | ||||||
|  |  | ||||||
| fn js_set_logger_callback(mut cx: FunctionContext) -> JsResult<JsUndefined> { |  | ||||||
|     let arg_cb = cx.argument::<JsFunction>(0)?; |  | ||||||
|     let cb_root = arg_cb.root(&mut cx); |  | ||||||
|     logger::set_logger_callback(Some(cb_root), &mut cx); |  | ||||||
|     Ok(cx.undefined()) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #[neon::main] | #[neon::main] | ||||||
| fn main(mut cx: ModuleContext) -> NeonResult<()> { | fn main(mut cx: ModuleContext) -> NeonResult<()> { | ||||||
|     logger::init_logger(&mut cx); |  | ||||||
|  |  | ||||||
|     cx.export_function("js_new_update_manager", js_new_update_manager)?; |     cx.export_function("js_new_update_manager", js_new_update_manager)?; | ||||||
|     cx.export_function("js_get_current_version", js_get_current_version)?; |     cx.export_function("js_get_current_version", js_get_current_version)?; | ||||||
|     cx.export_function("js_get_app_id", js_get_app_id)?; |     cx.export_function("js_get_app_id", js_get_app_id)?; | ||||||
| @@ -295,6 +293,5 @@ fn main(mut cx: ModuleContext) -> NeonResult<()> { | |||||||
|     cx.export_function("js_download_update_async", js_download_update_async)?; |     cx.export_function("js_download_update_async", js_download_update_async)?; | ||||||
|     cx.export_function("js_wait_exit_then_apply_update", js_wait_exit_then_apply_update)?; |     cx.export_function("js_wait_exit_then_apply_update", js_wait_exit_then_apply_update)?; | ||||||
|     cx.export_function("js_appbuilder_run", js_appbuilder_run)?; |     cx.export_function("js_appbuilder_run", js_appbuilder_run)?; | ||||||
|     cx.export_function("js_set_logger_callback", js_set_logger_callback)?; |  | ||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,98 +0,0 @@ | |||||||
| use std::sync::{Arc, Mutex}; |  | ||||||
|  |  | ||||||
| use lazy_static::lazy_static; |  | ||||||
| use log::{Level, Log, Metadata, Record}; |  | ||||||
| use neon::{event::Channel, prelude::*}; |  | ||||||
|  |  | ||||||
| static LOGGER: LoggerImpl = LoggerImpl {}; |  | ||||||
|  |  | ||||||
| lazy_static! { |  | ||||||
|     static ref LOGGER_CB: Arc<Mutex<Option<Root<JsFunction>>>> = Arc::new(Mutex::new(None)); |  | ||||||
|     static ref LOGGER_CONSOLE_LOG: Arc<Mutex<Option<Root<JsFunction>>>> = Arc::new(Mutex::new(None)); |  | ||||||
|     static ref LOGGER_CHANNEL: Arc<Mutex<Option<Channel>>> = Arc::new(Mutex::new(None)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| struct LoggerImpl {} |  | ||||||
|  |  | ||||||
| impl Log for LoggerImpl { |  | ||||||
|     fn enabled(&self, metadata: &Metadata) -> bool { |  | ||||||
|         metadata.level() <= log::max_level() |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     fn log(&self, record: &Record) { |  | ||||||
|         if !self.enabled(record.metadata()) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         let text = format!("{}", record.args()); |  | ||||||
|  |  | ||||||
|         let level = match record.level() { |  | ||||||
|             Level::Error => "error", |  | ||||||
|             Level::Warn => "warn", |  | ||||||
|             Level::Info => "info", |  | ||||||
|             Level::Debug => "debug", |  | ||||||
|             Level::Trace => "trace", |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         if let Ok(channel_opt) = LOGGER_CHANNEL.lock() { |  | ||||||
|             if channel_opt.is_some() { |  | ||||||
|                 let channel = channel_opt.as_ref().unwrap(); |  | ||||||
|  |  | ||||||
|                 channel.send(move |mut cx| { |  | ||||||
|                     // If custom callback exists, then use that. |  | ||||||
|                     if let Ok(cb_lock) = LOGGER_CB.lock() { |  | ||||||
|                         if let Some(cb) = &*cb_lock { |  | ||||||
|                             let undefined = cx.undefined(); |  | ||||||
|                             let args = vec![cx.string(level).upcast(), cx.string(text).upcast()]; |  | ||||||
|                             cb.to_inner(&mut cx).call(&mut cx, undefined, args)?; |  | ||||||
|                             return Ok(()); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|  |  | ||||||
|                     // If no custom callback, then use console.log |  | ||||||
|                     if let Ok(console) = LOGGER_CONSOLE_LOG.lock() { |  | ||||||
|                         if let Some(cb) = &*console { |  | ||||||
|                             let undefined = cx.undefined(); |  | ||||||
|                             let args = vec![cx.string(level).upcast(), cx.string(text).upcast()]; |  | ||||||
|                             cb.to_inner(&mut cx).call(&mut cx, undefined, args)?; |  | ||||||
|                             return Ok(()); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                     Ok(()) |  | ||||||
|                 }); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     fn flush(&self) {} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| pub fn init_logger(cx: &mut ModuleContext) { |  | ||||||
|     let _ = log::set_logger(&LOGGER); |  | ||||||
|     log::set_max_level(log::LevelFilter::Trace); |  | ||||||
|  |  | ||||||
|     if let Ok(mut ch) = LOGGER_CONSOLE_LOG.lock() { |  | ||||||
|         if let Ok(console) = cx.global::<JsObject>("console") { |  | ||||||
|             if let Ok(log_fn) = console.get::<JsFunction, ModuleContext, &str>(cx, "log") { |  | ||||||
|                 *ch = Some(log_fn.root(cx)); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if let Ok(mut ch) = LOGGER_CHANNEL.lock() { |  | ||||||
|         // let mut log_channel = Channel::new(cx); |  | ||||||
|         let mut log_channel = cx.channel(); |  | ||||||
|         log_channel.unref(cx); // Unref the channel so that the event loop can exit while this channel is open |  | ||||||
|         *ch = Some(log_channel); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| pub fn set_logger_callback(callback: Option<Root<JsFunction>>, cx: &mut FunctionContext) { |  | ||||||
|     if let Ok(mut cb_lock) = LOGGER_CB.lock() { |  | ||||||
|         let cb_taken = cb_lock.take(); |  | ||||||
|         if let Some(cb_exist) = cb_taken { |  | ||||||
|             cb_exist.drop(cx); |  | ||||||
|         } |  | ||||||
|         *cb_lock = callback; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -18,6 +18,7 @@ default = ["zstd"] | |||||||
| delta = ["zstd"] | delta = ["zstd"] | ||||||
| async = ["async-std"] | async = ["async-std"] | ||||||
| typescript = ["ts-rs"] | typescript = ["ts-rs"] | ||||||
|  | file-logging = ["log-panics", "simplelog", "file-rotate", "time"] | ||||||
|  |  | ||||||
| [package.metadata.docs.rs] | [package.metadata.docs.rs] | ||||||
| features = ["async", "delta"] | features = ["async", "delta"] | ||||||
| @@ -59,6 +60,12 @@ zstd = { workspace = true, optional = true } | |||||||
| # async | # async | ||||||
| async-std = { workspace = true, optional = true } | async-std = { workspace = true, optional = true } | ||||||
|  |  | ||||||
|  | # file logging | ||||||
|  | log-panics = { workspace = true, optional = true } | ||||||
|  | simplelog = { workspace = true, optional = true } | ||||||
|  | file-rotate = { workspace = true, optional = true } | ||||||
|  | time = { workspace = true, optional = true } | ||||||
|  |  | ||||||
| [target.'cfg(windows)'.dependencies] | [target.'cfg(windows)'.dependencies] | ||||||
| windows = { workspace = true, features = ["Win32_Foundation", "Win32_Storage", "Win32_Storage_FileSystem", "Win32_System_IO"] } | windows = { workspace = true, features = ["Win32_Foundation", "Win32_Storage", "Win32_Storage_FileSystem", "Win32_System_IO"] } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -103,6 +103,9 @@ pub mod delta; | |||||||
| /// Acquire and manage file-system based lock files. | /// Acquire and manage file-system based lock files. | ||||||
| pub mod lockfile; | pub mod lockfile; | ||||||
|  |  | ||||||
|  | /// Logging utilities and setup. | ||||||
|  | pub mod logging; | ||||||
|  |  | ||||||
| pub use app::*; | pub use app::*; | ||||||
| pub use manager::*; | pub use manager::*; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,37 +18,6 @@ pub fn default_channel_name() -> String { | |||||||
|     return "osx".to_owned(); |     return "osx".to_owned(); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Default log location for Velopack on the current OS. |  | ||||||
| #[allow(unused_variables)] |  | ||||||
| pub fn default_log_location(context: LocationContext) -> PathBuf { |  | ||||||
|     #[cfg(target_os = "windows")] |  | ||||||
|     { |  | ||||||
|         if let Ok(locator) = auto_locate_app_manifest(context) { |  | ||||||
|             return locator.get_root_dir().join("Velopack.log"); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         warn!("Could not auto-locate app manifest, writing log to current directory."); |  | ||||||
|  |  | ||||||
|         // If we can't locate the current app, we write to the current directory. |  | ||||||
|         let mut my_exe = std::env::current_exe().expect("Could not locate current executable"); |  | ||||||
|         my_exe.pop(); |  | ||||||
|         return my_exe.join("Velopack.log"); |  | ||||||
|     } |  | ||||||
|     #[cfg(target_os = "linux")] |  | ||||||
|     { |  | ||||||
|         return std::path::Path::new("/tmp/velopack.log").to_path_buf(); |  | ||||||
|     } |  | ||||||
|     #[cfg(target_os = "macos")] |  | ||||||
|     { |  | ||||||
|         #[allow(deprecated)] |  | ||||||
|         let mut user_home = std::env::home_dir().expect("Could not locate user home directory via $HOME or /etc/passwd"); |  | ||||||
|         user_home.push("Library"); |  | ||||||
|         user_home.push("Logs"); |  | ||||||
|         user_home.push("velopack.log"); |  | ||||||
|         return user_home; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bitflags::bitflags! { | bitflags::bitflags! { | ||||||
|     #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |     #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||||||
|     /// ShortcutLocationFlags is a bitflags enumeration of system shortcut locations. |     /// ShortcutLocationFlags is a bitflags enumeration of system shortcut locations. | ||||||
| @@ -121,8 +90,22 @@ pub struct VelopackLocator { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl VelopackLocator { | impl VelopackLocator { | ||||||
|  |     /// Creates a new VelopackLocator from the given paths, trying to auto-detect the manifest. | ||||||
|  |     pub fn new(config: &VelopackLocatorConfig) -> Result<VelopackLocator, Error> | ||||||
|  |     { | ||||||
|  |         if !config.UpdateExePath.exists() { | ||||||
|  |             return Err(Error::MissingUpdateExe); | ||||||
|  |         } | ||||||
|  |         if !config.ManifestPath.exists() { | ||||||
|  |             return Err(Error::MissingNuspec); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         let manifest = read_current_manifest(&config.ManifestPath)?; | ||||||
|  |         Ok(Self { paths: config.clone(), manifest }) | ||||||
|  |     } | ||||||
|  |      | ||||||
|     /// Creates a new VelopackLocator from the given paths and manifest. |     /// Creates a new VelopackLocator from the given paths and manifest. | ||||||
|     pub fn new(paths: VelopackLocatorConfig, manifest: Manifest) -> Self { |     pub fn new_with_manifest(paths: VelopackLocatorConfig, manifest: Manifest) -> Self { | ||||||
|         Self { paths, manifest } |         Self { paths, manifest } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -333,19 +316,6 @@ pub fn create_config_from_root_dir<P: AsRef<std::path::Path>>(root_dir: P) -> Ve | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| fn config_to_locator(config: &VelopackLocatorConfig) -> Result<VelopackLocator, Error> |  | ||||||
| { |  | ||||||
|     if !config.UpdateExePath.exists() { |  | ||||||
|         return Err(Error::MissingUpdateExe); |  | ||||||
|     } |  | ||||||
|     if !config.ManifestPath.exists() { |  | ||||||
|         return Err(Error::MissingNuspec); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     let manifest = read_current_manifest(&config.ManifestPath)?; |  | ||||||
|     Ok(VelopackLocator::new(config.clone(), manifest)) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// LocationContext is an enumeration of possible contexts for locating the current app manifest. | /// LocationContext is an enumeration of possible contexts for locating the current app manifest. | ||||||
| pub enum LocationContext | pub enum LocationContext | ||||||
| { | { | ||||||
| @@ -381,7 +351,7 @@ pub fn auto_locate_app_manifest(context: LocationContext) -> Result<VelopackLoca | |||||||
|         } |         } | ||||||
|         LocationContext::FromSpecifiedRootDir(root_dir) => { |         LocationContext::FromSpecifiedRootDir(root_dir) => { | ||||||
|             let config = create_config_from_root_dir(&root_dir); |             let config = create_config_from_root_dir(&root_dir); | ||||||
|             let locator = config_to_locator(&config)?; |             let locator = VelopackLocator::new(&config)?; | ||||||
|             return Ok(locator); |             return Ok(locator); | ||||||
|         } |         } | ||||||
|         LocationContext::FromSpecifiedAppExecutable(exe_path) => { |         LocationContext::FromSpecifiedAppExecutable(exe_path) => { | ||||||
| @@ -390,7 +360,7 @@ pub fn auto_locate_app_manifest(context: LocationContext) -> Result<VelopackLoca | |||||||
|                 if parent_dir.join("Update.exe").exists() { |                 if parent_dir.join("Update.exe").exists() { | ||||||
|                     info!("Found Update.exe in parent directory: {}", parent_dir.to_string_lossy()); |                     info!("Found Update.exe in parent directory: {}", parent_dir.to_string_lossy()); | ||||||
|                     let config = create_config_from_root_dir(&parent_dir); |                     let config = create_config_from_root_dir(&parent_dir); | ||||||
|                     let locator = config_to_locator(&config)?; |                     let locator = VelopackLocator::new(&config)?; | ||||||
|                     return Ok(locator); |                     return Ok(locator); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @@ -404,7 +374,7 @@ pub fn auto_locate_app_manifest(context: LocationContext) -> Result<VelopackLoca | |||||||
|                 if maybe_root.join("Update.exe").exists() { |                 if maybe_root.join("Update.exe").exists() { | ||||||
|                     info!("Found Update.exe by current path pattern search in directory: {}", maybe_root.to_string_lossy()); |                     info!("Found Update.exe by current path pattern search in directory: {}", maybe_root.to_string_lossy()); | ||||||
|                     let config = create_config_from_root_dir(&maybe_root); |                     let config = create_config_from_root_dir(&maybe_root); | ||||||
|                     let locator = config_to_locator(&config)?; |                     let locator = VelopackLocator::new(&config)?; | ||||||
|                     return Ok(locator); |                     return Ok(locator); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @@ -413,12 +383,12 @@ pub fn auto_locate_app_manifest(context: LocationContext) -> Result<VelopackLoca | |||||||
|             let exe_path = std::env::current_exe()?; |             let exe_path = std::env::current_exe()?; | ||||||
|             if let Some(parent_dir) = exe_path.parent() { |             if let Some(parent_dir) = exe_path.parent() { | ||||||
|                 let config = create_config_from_root_dir(&parent_dir); |                 let config = create_config_from_root_dir(&parent_dir); | ||||||
|                 let locator = config_to_locator(&config)?; |                 let locator = VelopackLocator::new(&config)?; | ||||||
|                 return Ok(locator); |                 return Ok(locator); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  |      | ||||||
|     Err(Error::NotInstalled("Could not auto-locate app manifest".to_owned())) |     Err(Error::NotInstalled("Could not auto-locate app manifest".to_owned())) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -472,7 +442,7 @@ pub fn auto_locate_app_manifest(context: LocationContext) -> Result<VelopackLoca | |||||||
|         IsPortable: true, |         IsPortable: true, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     config_to_locator(&config) |     Ok(VelopackLocator::new_with_manifest(config, app)) | ||||||
| } | } | ||||||
|  |  | ||||||
| #[cfg(target_os = "macos")] | #[cfg(target_os = "macos")] | ||||||
| @@ -520,8 +490,8 @@ pub fn auto_locate_app_manifest(context: LocationContext) -> Result<VelopackLoca | |||||||
|         CurrentBinaryDir: contents_dir, |         CurrentBinaryDir: contents_dir, | ||||||
|         IsPortable: true, |         IsPortable: true, | ||||||
|     }; |     }; | ||||||
|  |      | ||||||
|     config_to_locator(&config) |     Ok(VelopackLocator::new_with_manifest(config, app)) | ||||||
| } | } | ||||||
|  |  | ||||||
| fn read_current_manifest(nuspec_path: &PathBuf) -> Result<Manifest, Error> { | fn read_current_manifest(nuspec_path: &PathBuf) -> Result<Manifest, Error> { | ||||||
| @@ -569,7 +539,7 @@ fn test_locator_staged_id_for_new_user() { | |||||||
|     //Esure the packages directory exists |     //Esure the packages directory exists | ||||||
|     assert!(std::fs::create_dir_all(&paths.PackagesDir).is_ok()); |     assert!(std::fs::create_dir_all(&paths.PackagesDir).is_ok()); | ||||||
|  |  | ||||||
|     let locator = VelopackLocator::new(paths, Manifest::default()); |     let locator = VelopackLocator::new_with_manifest(paths, Manifest::default()); | ||||||
|  |  | ||||||
|     let staged_user_id = locator.get_staged_user_id(); |     let staged_user_id = locator.get_staged_user_id(); | ||||||
|  |  | ||||||
| @@ -596,7 +566,7 @@ fn test_locator_staged_id_for_existing_user() { | |||||||
|     //Esure the packages directory exists |     //Esure the packages directory exists | ||||||
|     assert!(std::fs::create_dir_all(&paths.PackagesDir).is_ok()); |     assert!(std::fs::create_dir_all(&paths.PackagesDir).is_ok()); | ||||||
|  |  | ||||||
|     let locator = VelopackLocator::new(paths, Manifest::default()); |     let locator = VelopackLocator::new_with_manifest(paths, Manifest::default()); | ||||||
|  |  | ||||||
|     let packages_dir = locator.get_packages_dir(); |     let packages_dir = locator.get_packages_dir(); | ||||||
|     let beta_id_path = packages_dir.join(".betaId"); |     let beta_id_path = packages_dir.join(".betaId"); | ||||||
|   | |||||||
							
								
								
									
										162
									
								
								src/lib-rust/src/logging.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								src/lib-rust/src/logging.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,162 @@ | |||||||
|  | #![allow(unused_variables)] | ||||||
|  |  | ||||||
|  | use crate::locator::{LocationContext, VelopackLocator, VelopackLocatorConfig}; | ||||||
|  | use std::path::PathBuf; | ||||||
|  |  | ||||||
|  | #[cfg(not(target_os = "windows"))] | ||||||
|  | use std::path::Path; | ||||||
|  |  | ||||||
|  | #[cfg(feature = "file-logging")] | ||||||
|  | use simplelog::*; | ||||||
|  | #[cfg(feature = "file-logging")] | ||||||
|  | use time::format_description::{modifier, Component, FormatItem}; | ||||||
|  |  | ||||||
|  | #[cfg(target_os = "linux")] | ||||||
|  | fn default_file_linux() -> PathBuf { | ||||||
|  |     Path::new("/tmp/velopack.log").to_path_buf() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[cfg(target_os = "macos")] | ||||||
|  | fn default_file_macos() -> PathBuf { | ||||||
|  |     #[allow(deprecated)] | ||||||
|  |     let user_home = std::env::home_dir(); | ||||||
|  |  | ||||||
|  |     if let Some(home) = user_home { | ||||||
|  |         let mut lib_logs = home.clone(); | ||||||
|  |         lib_logs.push("Library"); | ||||||
|  |         lib_logs.push("Logs"); | ||||||
|  |  | ||||||
|  |         if lib_logs.exists() { | ||||||
|  |             lib_logs.push("velopack.log"); | ||||||
|  |             return lib_logs; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return Path::new("/tmp/velopack.log").to_path_buf(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// Default log location for Velopack on the current OS. | ||||||
|  | #[allow(unused_variables)] | ||||||
|  | pub fn default_logfile_from_locator(locator: VelopackLocator) -> PathBuf { | ||||||
|  |     #[cfg(target_os = "windows")] | ||||||
|  |     { | ||||||
|  |         return locator.get_root_dir().join("Velopack.log"); | ||||||
|  |     } | ||||||
|  |     #[cfg(target_os = "linux")] | ||||||
|  |     { | ||||||
|  |         return default_file_linux(); | ||||||
|  |     } | ||||||
|  |     #[cfg(target_os = "macos")] | ||||||
|  |     { | ||||||
|  |         return default_file_macos(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// Default log location for Velopack on the current OS. | ||||||
|  | pub fn default_logfile_from_config(config: &VelopackLocatorConfig) -> PathBuf { | ||||||
|  |     #[cfg(target_os = "windows")] | ||||||
|  |     { | ||||||
|  |         match VelopackLocator::new(config) { | ||||||
|  |             Ok(locator) => { | ||||||
|  |                 return default_logfile_from_locator(locator); | ||||||
|  |             } | ||||||
|  |             Err(e) => warn!("Could not auto-locate app manifest, writing log to current directory. ({})", e), | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // If we can't locate the current app, we write to the current directory. | ||||||
|  |         let mut my_exe = std::env::current_exe().expect("Could not locate current executable"); | ||||||
|  |         my_exe.pop(); | ||||||
|  |         return my_exe.join("Velopack.log"); | ||||||
|  |     } | ||||||
|  |     #[cfg(target_os = "linux")] | ||||||
|  |     { | ||||||
|  |         return default_file_linux(); | ||||||
|  |     } | ||||||
|  |     #[cfg(target_os = "macos")] | ||||||
|  |     { | ||||||
|  |         return default_file_macos(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// Default log location for Velopack on the current OS. | ||||||
|  | #[allow(unused_variables)] | ||||||
|  | pub fn default_logfile_from_context(context: LocationContext) -> PathBuf { | ||||||
|  |     use crate::locator::{auto_locate_app_manifest}; | ||||||
|  |     #[cfg(target_os = "windows")] | ||||||
|  |     { | ||||||
|  |         match auto_locate_app_manifest(context) { | ||||||
|  |             Ok(locator) => { | ||||||
|  |                 return default_logfile_from_locator(locator); | ||||||
|  |             } | ||||||
|  |             Err(e) => warn!("Could not auto-locate app manifest, writing log to current directory. ({})", e), | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // If we can't locate the current app, we write to the current directory. | ||||||
|  |         let mut my_exe = std::env::current_exe().expect("Could not locate current executable"); | ||||||
|  |         my_exe.pop(); | ||||||
|  |         return my_exe.join("Velopack.log"); | ||||||
|  |     } | ||||||
|  |     #[cfg(target_os = "linux")] | ||||||
|  |     { | ||||||
|  |         return default_file_linux(); | ||||||
|  |     } | ||||||
|  |     #[cfg(target_os = "macos")] | ||||||
|  |     { | ||||||
|  |         return default_file_macos(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// Initialize logging for the current process. This will log optionally to a file and/or the console. | ||||||
|  | /// It can only be called once per process, and should be called early in the process lifecycle. | ||||||
|  | /// Future calls to this function will fail. | ||||||
|  | #[cfg(feature = "file-logging")] | ||||||
|  | pub fn init_logging(process_name: &str, file: Option<&PathBuf>, console: bool, verbose: bool) { | ||||||
|  |     let mut loggers: Vec<Box<dyn SharedLogger>> = Vec::new(); | ||||||
|  |     let color_choice = ColorChoice::Never; | ||||||
|  |     if console { | ||||||
|  |         let console_level = if verbose { LevelFilter::Debug } else { LevelFilter::Info }; | ||||||
|  |         loggers.push(TermLogger::new(console_level, get_config(None), TerminalMode::Mixed, color_choice)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if let Some(f) = file { | ||||||
|  |         let file_level = if verbose { LevelFilter::Trace } else { LevelFilter::Info }; | ||||||
|  |         let writer = file_rotate::FileRotate::new( | ||||||
|  |             f.clone(), | ||||||
|  |             file_rotate::suffix::AppendCount::new(1),          // keep 1 old log file | ||||||
|  |             file_rotate::ContentLimit::Bytes(1 * 1024 * 1024), // 1MB max log file size | ||||||
|  |             file_rotate::compression::Compression::None, | ||||||
|  |             None, | ||||||
|  |         ); | ||||||
|  |         loggers.push(WriteLogger::new(file_level, get_config(Some(process_name)), writer)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if let Ok(()) = CombinedLogger::init(loggers) { | ||||||
|  |         log_panics::init(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[cfg(feature = "file-logging")] | ||||||
|  | fn get_config(process_name: Option<&str>) -> Config { | ||||||
|  |     let mut c = ConfigBuilder::default(); | ||||||
|  |     let mut prefix = "".to_owned(); | ||||||
|  |     if let Some(pn) = process_name { | ||||||
|  |         prefix = format!("[{}:{}] ", pn, std::process::id()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     let prefix_heaped = Box::leak(prefix.into_boxed_str()); | ||||||
|  |  | ||||||
|  |     let time_format: &'static [FormatItem<'static>] = Box::leak(Box::new([ | ||||||
|  |         FormatItem::Literal(prefix_heaped.as_bytes()), | ||||||
|  |         FormatItem::Literal(b"["), | ||||||
|  |         FormatItem::Component(Component::Hour(modifier::Hour::default())), | ||||||
|  |         FormatItem::Literal(b":"), | ||||||
|  |         FormatItem::Component(Component::Minute(modifier::Minute::default())), | ||||||
|  |         FormatItem::Literal(b":"), | ||||||
|  |         FormatItem::Component(Component::Second(modifier::Second::default())), | ||||||
|  |         FormatItem::Literal(b"]"), | ||||||
|  |     ])); | ||||||
|  |  | ||||||
|  |     c.set_time_format_custom(time_format); | ||||||
|  |     let _ = c.set_time_offset_to_local(); // might fail if local tz can't be determined | ||||||
|  |     c.build() | ||||||
|  | } | ||||||
| @@ -173,8 +173,7 @@ impl UpdateManager { | |||||||
|     ) -> Result<UpdateManager, Error> { |     ) -> Result<UpdateManager, Error> { | ||||||
|         let locator = if let Some(config) = locator { |         let locator = if let Some(config) = locator { | ||||||
|             warn!("Using explicit locator configuration, ignoring auto-locate."); |             warn!("Using explicit locator configuration, ignoring auto-locate."); | ||||||
|             let manifest = config.load_manifest()?; |             VelopackLocator::new(&config)? | ||||||
|             VelopackLocator::new(config.clone(), manifest) |  | ||||||
|         } else { |         } else { | ||||||
|             locator::auto_locate_app_manifest(LocationContext::FromCurrentExe)? |             locator::auto_locate_app_manifest(LocationContext::FromCurrentExe)? | ||||||
|         }; |         }; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user