Skip to content

Commit

Permalink
more work on menuinst
Browse files Browse the repository at this point in the history
  • Loading branch information
wolfv committed Nov 9, 2024
1 parent cfa6b74 commit 29390e7
Show file tree
Hide file tree
Showing 12 changed files with 638 additions and 76 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ trybuild = { version = "1.0.101" }
typed-path = { version = "0.9.3" }
url = { version = "2.5.2" }
uuid = { version = "1.11.0", default-features = false }
unicode-normalization = { version = "0.1.24" }
walkdir = "2.5.0"
windows-sys = { version = "0.59.0", default-features = false }
zip = { version = "2.2.0", default-features = false }
Expand Down
1 change: 1 addition & 0 deletions crates/rattler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ memmap2 = { workspace = true }
once_cell = { workspace = true }
parking_lot = { workspace = true }
rattler_cache = { path = "../rattler_cache", version = "0.2.8", default-features = false }
rattler_menuinst = { path = "../rattler_menuinst", version = "0.1.0", default-features = false }
rattler_conda_types = { path = "../rattler_conda_types", version = "0.29.0", default-features = false }
rattler_digest = { path = "../rattler_digest", version = "1.0.3", default-features = false }
rattler_networking = { path = "../rattler_networking", version = "0.21.5", default-features = false }
Expand Down
39 changes: 38 additions & 1 deletion crates/rattler/src/install/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::{

use indexmap::IndexSet;
use itertools::Itertools;
use rattler_conda_types::{prefix_record::PathType, PackageRecord, PrefixRecord};
use rattler_conda_types::{prefix_record::PathType, PackageRecord, Platform, PrefixRecord};
use simple_spawn_blocking::{tokio::run_blocking_task, Cancelled};
use thiserror::Error;
use tokio::sync::{AcquireError, OwnedSemaphorePermit, Semaphore};
Expand Down Expand Up @@ -222,6 +222,43 @@ impl InstallDriver {
None
};

// find all files in `$PREFIX/menu/*.json` and install them with `menuinst`
if let Ok(read_dir) = target_prefix.join("menu").read_dir() {
for file in read_dir.flatten() {
let file = file.path();
if file.is_file() && file.extension().map_or(false, |ext| ext == "json") {
tracing::info!("Installing menu item: {:?}", file);
rattler_menuinst::install_menuitems(
&file,
target_prefix,
target_prefix,
&Platform::current(),
)
.unwrap_or_else(|e| {
tracing::warn!("Failed to install menu item: {} (ignored)", e);
});
}
}
}

// find all files in `$PREFIX/menu/*.json` and install them with `menuinst`
if let Ok(read_dir) = target_prefix.join("Menu").read_dir() {
for file in read_dir.flatten() {
let file = file.path();
if file.is_file() && file.extension().map_or(false, |ext| ext == "json") {
rattler_menuinst::install_menuitems(
&file,
target_prefix,
target_prefix,
&Platform::current(),
)
.unwrap_or_else(|e| {
tracing::warn!("Failed to install menu item: {} (ignored)", e);
});
}
}
}

Ok(PostProcessResult {
post_link_result,
clobbered_paths,
Expand Down
13 changes: 6 additions & 7 deletions crates/rattler_menuinst/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,13 @@ dirs = { workspace = true }
serde = { workspace = true, features = ["derive"] }
shlex = { workspace = true }
serde_json = { workspace = true }
sha1 = "0.10.6"
tracing.workspace = true
rattler_conda_types = { path="../rattler_conda_types", version = "0.27.2", default-features = false }
tracing = { workspace = true }
rattler_conda_types = { path = "../rattler_conda_types", default-features = false }
thiserror = { workspace = true }
unicode-normalization = "0.1.24"
regex.workspace = true
tempfile.workspace = true
fs-err = "2.11.0"
unicode-normalization = { workspace = true }
regex = { workspace = true }
tempfile = { workspace = true }
fs-err = { workspace = true }

[target.'cfg(target_os = "windows")'.dependencies]
winapi = "0.3.9"
Expand Down
4 changes: 2 additions & 2 deletions crates/rattler_menuinst/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ use rattler_conda_types::Platform;

mod linux;
mod macos;
#[cfg(target_os = "windows")]
mod windows;
mod render;
mod schema;
#[cfg(target_os = "windows")]
mod windows;

pub mod slugify;
pub use slugify::slugify;
Expand Down
9 changes: 7 additions & 2 deletions crates/rattler_menuinst/src/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use crate::MenuMode;
use crate::{schema::Linux, MenuInstError};

pub struct LinuxMenu {
name: String,
item: Linux,

Check failure on line 28 in crates/rattler_menuinst/src/linux.rs

View workflow job for this annotation

GitHub Actions / Format, Lint and Test the Python bindings

field `item` is never read

Check failure on line 28 in crates/rattler_menuinst/src/linux.rs

View workflow job for this annotation

GitHub Actions / Format and Lint

field `item` is never read

Check failure on line 28 in crates/rattler_menuinst/src/linux.rs

View workflow job for this annotation

GitHub Actions / Check intra-doc links

field `item` is never read
directories: Directories,
}
Expand Down Expand Up @@ -70,14 +71,18 @@ impl Directories {
impl LinuxMenu {
fn new(item: Linux, mode: MenuMode) -> Self {
LinuxMenu {
name: item
.base
.get_name(crate::schema::Environment::Base)
.to_string(),
item,
directories: Directories::new(mode),
}
}

fn location(&self) -> PathBuf {
// TODO: The Python implementation uses one more variable
let filename = format!("{}.desktop", self.item.base.name);
let filename = format!("{}.desktop", self.name);
self.directories.desktop_entries_location.join(filename)
}

Expand Down Expand Up @@ -151,7 +156,7 @@ impl LinuxMenu {
writeln!(writer, "[Desktop Entry]")?;
writeln!(writer, "Type=Application")?;
writeln!(writer, "Encoding=UTF-8")?;
writeln!(writer, "Name={}", self.item.base.name)?;
writeln!(writer, "Name={:?}", self.item.base.name)?;
writeln!(writer, "Exec={}", self.item.base.command.join(" "))?;
writeln!(
writer,
Expand Down
91 changes: 54 additions & 37 deletions crates/rattler_menuinst/src/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::{schema::MacOS, slugify, utils, MenuInstError, MenuMode};
use fs_err as fs;
use fs_err::File;
use plist::Value;
use sha1::{Digest, Sha1};
use std::{
io::{BufWriter, Write},
os::unix::fs::PermissionsExt,
Expand All @@ -11,6 +10,7 @@ use std::{
};

pub struct MacOSMenu {
name: String,
prefix: PathBuf,

Check failure on line 14 in crates/rattler_menuinst/src/macos.rs

View workflow job for this annotation

GitHub Actions / Format, Lint and Test the Python bindings

field `prefix` is never read

Check failure on line 14 in crates/rattler_menuinst/src/macos.rs

View workflow job for this annotation

GitHub Actions / Format and Lint

field `prefix` is never read

Check failure on line 14 in crates/rattler_menuinst/src/macos.rs

View workflow job for this annotation

GitHub Actions / Check intra-doc links

field `prefix` is never read
item: MacOS,
directories: Directories,
Expand Down Expand Up @@ -63,6 +63,10 @@ impl Directories {
impl MacOSMenu {
pub fn new(prefix: &Path, item: MacOS, directories: Directories) -> Self {
Self {
name: item
.base
.get_name(crate::schema::Environment::Base)
.to_string(),
prefix: prefix.to_path_buf(),
item,
directories,
Expand Down Expand Up @@ -111,7 +115,7 @@ impl MacOSMenu {
f.write_all(format!("APPL{short_name}").as_bytes())?;
Ok(())
};
let short_name = slugify(&self.item.base.name.chars().take(8).collect::<String>());
let short_name = slugify(&self.name.chars().take(8).collect::<String>());

create_pkg_info(&self.directories.location, &short_name)?;
if self.needs_appkit_launcher() {
Expand All @@ -122,11 +126,12 @@ impl MacOSMenu {
}

fn write_plist_info(&self) -> Result<(), MenuInstError> {
let name = self.item.base.name.clone();
let name = self.name.clone();
let slugname = slugify(&name);

let shortname = if slugname.len() > 16 {
let hashed = format!("{:x}", Sha1::digest(slugname.as_bytes()));
// let hashed = format!("{:x}", Sha256::digest(slugname.as_bytes()));
let hashed = "123456";
format!("{}{}", &slugname[..10], &hashed[..6])
} else {
slugname.clone()
Expand Down Expand Up @@ -158,7 +163,13 @@ impl MacOSMenu {
}

if self.needs_appkit_launcher() {
println!("Writing plist to {}", self.directories.nested_location.join("Contents/Info.plist").display());
println!(
"Writing plist to {}",
self.directories
.nested_location
.join("Contents/Info.plist")
.display()
);
plist::to_file_xml(
self.directories.nested_location.join("Contents/Info.plist"),
&pl,
Expand All @@ -181,13 +192,13 @@ impl MacOSMenu {
pl.insert("LSBackgroundOnly".into(), Value::Boolean(background_only));
}

self.item.ls_environment.as_ref().map(|env| {
if let Some(env) = self.item.ls_environment.as_ref() {
let mut env_dict = plist::Dictionary::new();
for (k, v) in env {
env_dict.insert(k.into(), Value::String(v.into()));
}
pl.insert("LSEnvironment".into(), Value::Dictionary(env_dict));
});
}

if let Some(version) = self.item.ls_minimum_system_version.as_ref() {
pl.insert(
Expand Down Expand Up @@ -239,29 +250,35 @@ impl MacOSMenu {
// pl.insert("UTExportedTypeDeclarations".into(), Value::Array(type_array));
});

self.item
.ut_imported_type_declarations
.as_ref()
.map(|_types| {
// let mut type_array = Vec::new();
// for t in types {
// let mut type_dict = plist::Dictionary::new();
// type_dict.insert("UTTypeConformsTo".into(), Value::Array(t.ut_type_conforms_to.iter().map(|s| Value::String(s.clone())).collect()));
// type_dict.insert("UTTypeDescription".into(), Value::String(t.ut_type_description.clone().unwrap_or_default()));
// type_dict.insert("UTTypeIconFile".into(), Value::String(t.ut_type_icon_file.clone().unwrap_or_default()));
// type_dict.insert("UTTypeIdentifier".into(), Value::String(t.ut_type_identifier.clone()));
// type_dict.insert("UTTypeReferenceURL".into(), Value::String(t.ut_type_reference_url.clone().unwrap_or_default()));
// let mut tag_spec = plist::Dictionary::new();
// for (k, v) in &t.ut_type_tag_specification {
// tag_spec.insert(k.clone(), Value::Array(v.iter().map(|s| Value::String(s.clone())).collect()));
// }
// type_dict.insert("UTTypeTagSpecification".into(), Value::Dictionary(tag_spec));
// type_array.push(Value::Dictionary(type_dict));
// }
// pl.insert("UTImportedTypeDeclarations".into(), Value::Array(type_array));
});

println!("Writing plist to {}", self.directories.location.join("Contents/Info.plist").display());
// self.item
// .ut_imported_type_declarations
// .as_ref()
// .map(|_types| {
// // let mut type_array = Vec::new();
// // for t in types {
// // let mut type_dict = plist::Dictionary::new();
// // type_dict.insert("UTTypeConformsTo".into(), Value::Array(t.ut_type_conforms_to.iter().map(|s| Value::String(s.clone())).collect()));
// // type_dict.insert("UTTypeDescription".into(), Value::String(t.ut_type_description.clone().unwrap_or_default()));
// // type_dict.insert("UTTypeIconFile".into(), Value::String(t.ut_type_icon_file.clone().unwrap_or_default()));
// // type_dict.insert("UTTypeIdentifier".into(), Value::String(t.ut_type_identifier.clone()));
// // type_dict.insert("UTTypeReferenceURL".into(), Value::String(t.ut_type_reference_url.clone().unwrap_or_default()));
// // let mut tag_spec = plist::Dictionary::new();
// // for (k, v) in &t.ut_type_tag_specification {
// // tag_spec.insert(k.clone(), Value::Array(v.iter().map(|s| Value::String(s.clone())).collect()));
// // }
// // type_dict.insert("UTTypeTagSpecification".into(), Value::Dictionary(tag_spec));
// // type_array.push(Value::Dictionary(type_dict));
// // }
// // pl.insert("UTImportedTypeDeclarations".into(), Value::Array(type_array));
// });

println!(
"Writing plist to {}",
self.directories
.location
.join("Contents/Info.plist")
.display()
);
plist::to_file_xml(self.directories.location.join("Contents/Info.plist"), &pl)?;

Ok(())
Expand Down Expand Up @@ -296,7 +313,7 @@ impl MacOSMenu {
.arg("--options")
.arg("runtime")
.arg("--prefix")
.arg(format!("com.{}", slugify(&self.item.base.name)))
.arg(format!("com.{}", slugify(&self.name)))
.arg("--entitlements")
.arg(&entitlements_file)
.arg(self.directories.location.to_str().unwrap())
Expand Down Expand Up @@ -441,12 +458,12 @@ impl MacOSMenu {
}

fn default_appkit_launcher_path(&self) -> PathBuf {
let name = slugify(&self.item.base.name);
let name = slugify(&self.name);
self.directories.location.join("Contents/MacOS").join(&name)
}

fn default_launcher_path(&self) -> PathBuf {
let name = slugify(&self.item.base.name);
let name = slugify(&self.name);
if self.needs_appkit_launcher() {
self.directories
.nested_location
Expand All @@ -463,9 +480,9 @@ impl MacOSMenu {
}

if register {
self.lsregister(&["-R", self.directories.location.to_str().unwrap()])
Self::lsregister(&["-R", self.directories.location.to_str().unwrap()])
} else {
self.lsregister(&[
Self::lsregister(&[
"-R",
"-u",
"-all",
Expand All @@ -474,7 +491,7 @@ impl MacOSMenu {
}
}

fn lsregister(&self, args: &[&str]) -> Result<(), MenuInstError> {
fn lsregister(args: &[&str]) -> Result<(), MenuInstError> {
let exe = "/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister";

let output = Command::new(exe).args(args).output().map_err(|e| {
Expand Down Expand Up @@ -523,7 +540,7 @@ pub(crate) fn install_menu_item(
) -> Result<(), MenuInstError> {
let bundle_name = macos_item.cf_bundle_name.as_ref().unwrap();
let directories = Directories::new(menu_mode, bundle_name);
println!("Installing menu item for {}", bundle_name);
println!("Installing menu item for {bundle_name}");
let menu = MacOSMenu::new(prefix, macos_item, directories);
menu.install()
}
Expand Down
Loading

0 comments on commit 29390e7

Please sign in to comment.