Remove logging callbacks from C++ / NodeJS

This commit is contained in:
Caelan Sayler
2025-03-03 21:06:48 +00:00
committed by Caelan
parent 60890b7bba
commit ec3b6561de
21 changed files with 239 additions and 337 deletions

4
Cargo.lock generated
View File

@@ -2209,10 +2209,12 @@ dependencies = [
"async-std",
"bitflags 2.9.0",
"derivative",
"file-rotate",
"glob",
"lazy_static",
"libc",
"log",
"log-panics",
"normpath",
"rand",
"regex",
@@ -2221,8 +2223,10 @@ dependencies = [
"serde_json",
"sha1",
"sha2",
"simplelog",
"tempfile",
"thiserror 2.0.12",
"time 0.3.37",
"ts-rs",
"ureq",
"url",

View File

@@ -23,7 +23,7 @@ edition = "2021"
rust-version = "1.75"
[workspace.dependencies]
velopack = { path = "src/lib-rust" }
velopack = { path = "src/lib-rust", features = ["file-logging"] }
log = "0.4"
log-derive = "0.4.1"
ureq = "3.0"

View File

@@ -116,7 +116,7 @@ pub fn install(pkg: &mut BundleZip, install_to: Option<&PathBuf>, start_args: Op
info!("Acquiring lock...");
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 tx = if dialogs::get_silent() {

View File

@@ -156,7 +156,7 @@ fn try_legacy_migration(root_dir: &PathBuf, manifest: &Manifest) -> Result<Velop
// new shortcuts will be force-created
let mut modified_manifest = manifest.clone();
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()?;
if !locator.get_current_bin_dir().exists() {

View File

@@ -1,5 +1,4 @@
pub mod commands;
pub mod logging;
pub mod shared;
#[cfg(target_os = "windows")]
pub mod windows;
@@ -8,6 +7,5 @@ pub use shared::dialogs;
#[macro_use]
extern crate log;
extern crate simplelog;
#[macro_use]
extern crate lazy_static;

View File

@@ -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()
}

View File

@@ -79,7 +79,7 @@ fn main_inner() -> Result<()> {
let verbose = matches.get_flag("verbose");
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 install_to = matches.get_one::<PathBuf>("installto");

View File

@@ -1,8 +1,6 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
#![allow(dead_code)]
mod logging;
#[macro_use]
extern crate log;
@@ -21,7 +19,7 @@ fn main() -> ExitCode {
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!("Starting Velopack Stub (at {:?})", my_path);

View File

@@ -7,8 +7,9 @@ extern crate log;
use anyhow::{anyhow, bail, Result};
use clap::{arg, value_parser, ArgMatches, Command};
use std::{env, path::PathBuf};
use velopack::locator::{self, auto_locate_app_manifest, LocationContext};
use velopack_bins::{*, shared::OperationWait};
use velopack::locator::{auto_locate_app_manifest, LocationContext};
use velopack::logging::*;
use velopack_bins::{shared::OperationWait, *};
#[rustfmt::skip]
fn root_command() -> Command {
@@ -132,8 +133,8 @@ fn main() -> Result<()> {
let verbose = get_flag_or_false(&matches, "verbose");
let log_file = matches.get_one("log");
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)?;
let desired_log_file = log_file.cloned().unwrap_or(default_logfile_from_context(LocationContext::IAmUpdateExe));
init_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()?;
@@ -212,7 +213,6 @@ fn apply(matches: &ArgMatches) -> Result<()> {
Ok(())
}
fn get_start_args(matches: &ArgMatches) -> (OperationWait, Option<&String>, Option<&String>, Option<Vec<&str>>) {
let legacy_args = matches.get_one::<String>("args");
let exe_name = matches.get_one::<String>("EXE_NAME");
@@ -246,7 +246,7 @@ fn uninstall(_matches: &ArgMatches) -> Result<()> {
#[cfg(target_os = "windows")]
#[test]
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 (wait, restart, package, exe_args) = get_apply_args(matches.subcommand_matches("apply").unwrap());

View File

@@ -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);
/**
* Log callback function.
*/
typedef void (*vpkc_log_callback_t)(void *p_user_data,
const char *psz_level,
const char *psz_message);
#ifdef __cplusplus
extern "C" {
#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);
/**
* 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
} // extern "C"
#endif // __cplusplus

View File

@@ -16,6 +16,8 @@ use libc::{c_char, c_void, size_t};
use log_derive::{logfn, logfn_inputs};
use std::{ffi::CString, ptr};
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.
#[no_mangle]
@@ -438,6 +440,14 @@ pub extern "C" fn vpkc_app_run(p_user_data: *mut c_void) {
});
}
// 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();
}
@@ -531,9 +541,3 @@ pub extern "C" fn vpkc_get_last_error(psz_error: *mut c_char, c_error: size_t) -
let error = get_last_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);
}

View File

@@ -1,7 +1,5 @@
use anyhow::Result;
use log::{Level, Log, Metadata, Record};
use std::ffi::{c_void, CString};
use std::sync::{Mutex, RwLock};
use std::sync::RwLock;
use velopack::locator::VelopackLocatorConfig;
use crate::types::*;
@@ -21,7 +19,6 @@ pub struct AppOptions {
lazy_static::lazy_static! {
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());
}
@@ -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) {}
}

View File

@@ -22,9 +22,6 @@ pub type vpkc_update_source_t = c_void;
/// Progress callback function.
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.
pub type vpkc_hook_callback_t = Option<extern "C" fn(p_user_data: *mut c_void, psz_app_version: *const c_char)>;

View File

@@ -47,10 +47,6 @@ declare module "./load" {
locator: string | null,
autoApply: boolean,
): void;
function js_set_logger_callback(
cb: (loglevel: LogLevel, msg: string) => void,
): void;
}
type VelopackHookType =
@@ -63,8 +59,6 @@ type VelopackHookType =
type VelopackHook = (version: string) => void;
type LogLevel = "info" | "warn" | "error" | "debug" | "trace";
/**
* VelopackApp helps you to handle app activation events correctly.
* This should be used as early as possible in your application startup code.
@@ -301,12 +295,3 @@ export class UpdateManager {
);
}
}
/**
* 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);
}

View File

@@ -7,8 +7,7 @@ use std::sync::{Arc, Mutex};
use std::thread;
use velopack::sources::*;
use velopack::*;
mod logger;
use velopack::logging::{default_logfile_from_config, default_logfile_from_context};
struct UpdateManagerWrapper {
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));
}
if let Some(locator) = locator {
builder = builder.set_locator(locator);
if let Some(locator) = &locator {
builder = builder.set_locator(locator.clone());
}
if let Some(arg_array) = argarray {
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();
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]
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_get_current_version", js_get_current_version)?;
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_wait_exit_then_apply_update", js_wait_exit_then_apply_update)?;
cx.export_function("js_appbuilder_run", js_appbuilder_run)?;
cx.export_function("js_set_logger_callback", js_set_logger_callback)?;
Ok(())
}

View File

@@ -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;
}
}

View File

@@ -18,6 +18,7 @@ default = ["zstd"]
delta = ["zstd"]
async = ["async-std"]
typescript = ["ts-rs"]
file-logging = ["log-panics", "simplelog", "file-rotate", "time"]
[package.metadata.docs.rs]
features = ["async", "delta"]
@@ -59,6 +60,12 @@ zstd = { workspace = true, optional = true }
# async
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]
windows = { workspace = true, features = ["Win32_Foundation", "Win32_Storage", "Win32_Storage_FileSystem", "Win32_System_IO"] }

View File

@@ -103,6 +103,9 @@ pub mod delta;
/// Acquire and manage file-system based lock files.
pub mod lockfile;
/// Logging utilities and setup.
pub mod logging;
pub use app::*;
pub use manager::*;

View File

@@ -18,37 +18,6 @@ pub fn default_channel_name() -> String {
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! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
/// ShortcutLocationFlags is a bitflags enumeration of system shortcut locations.
@@ -121,8 +90,22 @@ pub struct 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.
pub fn new(paths: VelopackLocatorConfig, manifest: Manifest) -> Self {
pub fn new_with_manifest(paths: VelopackLocatorConfig, manifest: Manifest) -> Self {
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.
pub enum LocationContext
{
@@ -381,7 +351,7 @@ pub fn auto_locate_app_manifest(context: LocationContext) -> Result<VelopackLoca
}
LocationContext::FromSpecifiedRootDir(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);
}
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() {
info!("Found Update.exe in parent directory: {}", parent_dir.to_string_lossy());
let config = create_config_from_root_dir(&parent_dir);
let locator = config_to_locator(&config)?;
let locator = VelopackLocator::new(&config)?;
return Ok(locator);
}
}
@@ -404,7 +374,7 @@ pub fn auto_locate_app_manifest(context: LocationContext) -> Result<VelopackLoca
if maybe_root.join("Update.exe").exists() {
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 locator = config_to_locator(&config)?;
let locator = VelopackLocator::new(&config)?;
return Ok(locator);
}
}
@@ -413,7 +383,7 @@ pub fn auto_locate_app_manifest(context: LocationContext) -> Result<VelopackLoca
let exe_path = std::env::current_exe()?;
if let Some(parent_dir) = exe_path.parent() {
let config = create_config_from_root_dir(&parent_dir);
let locator = config_to_locator(&config)?;
let locator = VelopackLocator::new(&config)?;
return Ok(locator);
}
}
@@ -472,7 +442,7 @@ pub fn auto_locate_app_manifest(context: LocationContext) -> Result<VelopackLoca
IsPortable: true,
};
config_to_locator(&config)
Ok(VelopackLocator::new_with_manifest(config, app))
}
#[cfg(target_os = "macos")]
@@ -521,7 +491,7 @@ pub fn auto_locate_app_manifest(context: LocationContext) -> Result<VelopackLoca
IsPortable: true,
};
config_to_locator(&config)
Ok(VelopackLocator::new_with_manifest(config, app))
}
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
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();
@@ -596,7 +566,7 @@ fn test_locator_staged_id_for_existing_user() {
//Esure the packages directory exists
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 beta_id_path = packages_dir.join(".betaId");

162
src/lib-rust/src/logging.rs Normal file
View 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()
}

View File

@@ -173,8 +173,7 @@ impl UpdateManager {
) -> Result<UpdateManager, Error> {
let locator = if let Some(config) = locator {
warn!("Using explicit locator configuration, ignoring auto-locate.");
let manifest = config.load_manifest()?;
VelopackLocator::new(config.clone(), manifest)
VelopackLocator::new(&config)?
} else {
locator::auto_locate_app_manifest(LocationContext::FromCurrentExe)?
};