diff --git a/native/Cargo.lock b/native/Cargo.lock index 191f6d2a..dea1a091 100644 --- a/native/Cargo.lock +++ b/native/Cargo.lock @@ -203,6 +203,19 @@ version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +[[package]] +name = "blake3" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", +] + [[package]] name = "brotli" version = "3.4.0" @@ -390,6 +403,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + [[package]] name = "core-foundation" version = "0.9.4" @@ -639,6 +658,7 @@ version = "0.0.0" dependencies = [ "ab_glyph", "anyhow", + "blake3", "byteorder", "bzip2", "cfg-if", diff --git a/native/Cargo.toml b/native/Cargo.toml index 0f5f440e..5e2d6df1 100644 --- a/native/Cargo.toml +++ b/native/Cargo.toml @@ -27,6 +27,7 @@ immutable-runtime = [] [dependencies] ab_glyph = "0.2.23" anyhow = "1.0.79" +blake3 = "1.5.0" byteorder = "1.5.0" cfg-if = "1.0.0" clap = { version = "^4.4.18", features = ["derive"] } diff --git a/native/src/components/runtime.rs b/native/src/components/runtime.rs index 7cc99bd5..7546c191 100644 --- a/native/src/components/runtime.rs +++ b/native/src/components/runtime.rs @@ -1,9 +1,10 @@ -use std::fs::{read_dir, remove_dir_all, remove_file}; -use std::io::Result as IoResult; +use std::fs::{read_dir, remove_dir_all, remove_file, File}; +use std::io::{Read, Result as IoResult}; use std::path::{Path, PathBuf}; use std::process::{Child, Command}; use anyhow::{anyhow, Context, Result}; +use blake3::Hasher; use cfg_if::cfg_if; use configparser::ini::Ini; use fs_extra::dir::{copy, CopyOptions}; @@ -13,6 +14,17 @@ use tempfile::{NamedTempFile, TempDir}; use crate::components::site::Site; use crate::directories::ProjectDirs; +// TODO: Remove this constant and implement variable firefox path into user documentation +pub const FFOX: &str = "/usr/lib/firefox/"; + +pub fn b3hasher() -> String { + let mut file = File::open(Path::new(FFOX).join("firefox")).unwrap(); + let mut buf = Vec::new(); + let _ = file.read_to_end(&mut buf); + + Hasher::new().update(&buf).finalize().to_string() +} + cfg_if! { if #[cfg(any(platform_linux, platform_bsd))] { @@ -288,23 +300,21 @@ impl Runtime { #[cfg(all(any(target_os = "linux", target_os = "bsd"), not(feature = "immutable-runtime")))] pub fn link(&self) -> Result<()> { + use crate::storage::Storage; use std::fs::{copy, create_dir_all}; use std::os::unix::fs::symlink; - use crate::storage::Storage; - let dirs = ProjectDirs::new()?; let mut storage = Storage::load(&dirs)?; self.uninstall()?; storage.config.use_linked_runtime = true; - storage.write(&dirs)?; info!("Linking the runtime"); - if Path::new("/usr/lib/firefox/").exists() { - for entry in read_dir("/usr/lib/firefox/")?.flatten() { + if Path::new(FFOX).exists() { + for entry in read_dir(FFOX)?.flatten() { let entry = entry.path(); match entry.file_name().expect("Couldn't retrieve a file name").to_str() { // Use a different branch for the "defaults" folder due to the patches to apply afterwhile @@ -320,6 +330,10 @@ impl Runtime { } Some("firefox") => { copy(entry, self.directory.join("firefox"))?; + + storage.config.hash = b3hasher(); + + trace!("Hash: {}", b3hasher()); } Some(&_) => { let link = self.directory.join(entry.file_name().unwrap()); @@ -330,6 +344,8 @@ impl Runtime { } } + storage.write(&dirs)?; + info!("Runtime linked!"); Ok(()) diff --git a/native/src/console/site.rs b/native/src/console/site.rs index 9990952e..ae5730b8 100644 --- a/native/src/console/site.rs +++ b/native/src/console/site.rs @@ -12,17 +12,14 @@ use url::Url; use crate::components::runtime::Runtime; use crate::components::site::{Site, SiteConfig}; use crate::console::app::{ - SiteInstallCommand, - SiteLaunchCommand, - SiteUninstallCommand, - SiteUpdateCommand, + SiteInstallCommand, SiteLaunchCommand, SiteUninstallCommand, SiteUpdateCommand, }; use crate::console::{store_value, store_value_vec, Run}; use crate::directories::ProjectDirs; -use crate::integrations; use crate::integrations::{IntegrationInstallArgs, IntegrationUninstallArgs}; use crate::storage::Storage; use crate::utils::construct_certificates_and_client; +use crate::{components, integrations}; impl Run for SiteLaunchCommand { fn run(&self) -> Result<()> { @@ -50,6 +47,11 @@ impl Run for SiteLaunchCommand { bail!("Runtime not installed"); } + if storage.config.hash != components::runtime::b3hasher() && !storage.config.hash.is_empty() + { + runtime.link()?; + } + // Patching on macOS is always needed to correctly show the web app name // Otherwise, patch runtime and profile only if needed let should_patch = if cfg!(platform_macos) || storage.config.always_patch { diff --git a/native/src/storage.rs b/native/src/storage.rs index f01bd2db..f6424df2 100644 --- a/native/src/storage.rs +++ b/native/src/storage.rs @@ -49,10 +49,11 @@ pub struct Config { /// May be overwritten with a system environment variable. pub runtime_use_portals: bool, - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "bsd"))] /// Experimental: Using the system runtime to save some disk space. /// This might not work on your system. pub use_linked_runtime: bool, + pub hash: String, } #[non_exhaustive]