From a9e4fa28ebb2c4a4ff5a3654496f063e33608473 Mon Sep 17 00:00:00 2001 From: Kaydax Date: Tue, 5 May 2026 16:06:01 -0400 Subject: [PATCH] Fix dvm for latest discord update - Fix script to launch the discord binary directly. The latest update moved it - Fix the remove script panicing when there is no .desktop or icon files - Properly patch the .desktop file to use the dvm binary instead of the discord binary Signed-off-by: Kaydax --- Cargo.lock | 4 ++-- src/cli/remove.rs | 60 +++++++++++++++++++++++++++++------------------ src/path.rs | 27 +++++++++++++++++++-- src/util.rs | 48 ++++++++++++++++++------------------- 4 files changed, 88 insertions(+), 51 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0a11988..1e851ae 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -215,7 +215,7 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "dvm" -version = "1.2.0" +version = "1.3.0" dependencies = [ "clap", "clap_complete", diff --git a/src/cli/remove.rs b/src/cli/remove.rs index 0534365..697fca6 100755 --- a/src/cli/remove.rs +++ b/src/cli/remove.rs @@ -1,4 +1,8 @@ -use std::{fs, path::Path}; +use std::{ + fs, + io::ErrorKind, + path::Path, +}; use crate::{branch::DiscordBranch, error, info, path as dvm_path, success, Res}; @@ -14,8 +18,7 @@ pub async fn remove(release_type: DiscordBranch, verbose: bool) -> Res<()> { error!("{} not installed", release_type); } - let version = fs::read_to_string(dvm_path::version_file(release_type)?) - .expect("could not read version file: malformed installation detected"); + let version = fs::read_to_string(dvm_path::version_file(release_type)?)?; if verbose { info!("reading version file") } @@ -23,38 +26,49 @@ pub async fn remove(release_type: DiscordBranch, verbose: bool) -> Res<()> { info!("removing version {}:{}", release_type, version); // remove all {release type} associated files - fs::remove_dir_all(dvm_path::install_dir(release_type)?) - .expect("error when removing data dirs"); + if let Err(e) = fs::remove_dir_all(dvm_path::install_dir(release_type)?) { + if e.kind() != ErrorKind::NotFound { + return Err(e.into()); + } + } if verbose { info!("removed data dirs") } - fs::remove_file(dvm_path::dvm_bin_dir()?.join(dvm_path::pkg_name(release_type))) - .expect("error when removing bin file"); + let bin_file = dvm_path::dvm_bin_dir()?.join(dvm_path::pkg_name(release_type)); + if let Err(e) = fs::remove_file(&bin_file) { + if e.kind() != ErrorKind::NotFound { + return Err(e.into()); + } + } if verbose { info!("removed bin file") } - fs::remove_file( - dvm_path::home_dir()? - .join(".local") - .join("share") - .join("applications") - .join(format!("{}.desktop", dvm_path::pkg_name(release_type))), - ) - .expect("error when removing desktop file"); + let desktop_file = dvm_path::home_dir()? + .join(".local") + .join("share") + .join("applications") + .join(format!("{}.desktop", dvm_path::pkg_name(release_type))); + if let Err(e) = fs::remove_file(&desktop_file) { + if e.kind() != ErrorKind::NotFound { + return Err(e.into()); + } + } if verbose { info!("removed desktop file") } - fs::remove_file( - dvm_path::home_dir()? - .join(".local") - .join("share") - .join("icons") - .join(format!("{}.png", dvm_path::pkg_name(release_type))), - ) - .expect("error when removing icon"); + let icon_file = dvm_path::home_dir()? + .join(".local") + .join("share") + .join("icons") + .join(format!("{}.png", dvm_path::pkg_name(release_type))); + if let Err(e) = fs::remove_file(&icon_file) { + if e.kind() != ErrorKind::NotFound { + return Err(e.into()); + } + } if verbose { info!("removed icon") } diff --git a/src/path.rs b/src/path.rs index fa3c284..0f576b8 100644 --- a/src/path.rs +++ b/src/path.rs @@ -58,16 +58,39 @@ pub fn app_dir(branch: DiscordBranch) -> Res { return Ok(install); } + let mut best_match: Option<(Vec, PathBuf)> = None; for entry in fs::read_dir(&install)? { let entry = entry?; let path = entry.path(); if !path.is_dir() { continue; } + + let Some(name) = path.file_name().and_then(|n| n.to_str()) else { + continue; + }; + let Some(version) = name.strip_prefix("app-") else { + continue; + }; + let candidate = path.join("resources").join("app.asar"); - if candidate.exists() { - return Ok(path); + if !candidate.exists() { + continue; } + + let parsed = version + .split('.') + .map(|part| part.parse::().unwrap_or(0)) + .collect::>(); + + match &best_match { + Some((best_version, _)) if &parsed <= best_version => {} + _ => best_match = Some((parsed, path)), + } + } + + if let Some((_, path)) = best_match { + return Ok(path); } Ok(install) diff --git a/src/util.rs b/src/util.rs index 03ec483..244f926 100755 --- a/src/util.rs +++ b/src/util.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, fs, path::Path}; +use std::{collections::HashMap, fs}; use tokio::process::Command; @@ -124,20 +124,19 @@ pub async fn install_version( } } - let app_dir = dvm_path::app_dir(release_type)?; + // patch desktop entry to point to dvm launcher bin + let desktop_source = install_dir.join(format!("{}.desktop", pkg_name)); - let desktop_file = app_dir.join(format!("{}.desktop", pkg_name)); - if Path::new(&desktop_file).exists() { + if desktop_source.exists() { Command::new("sed") .arg("-i") .arg(format!( - "s#/usr/share/{}/{}#{}/{}#", + "s#/usr/bin/{}#{}/{}#", pkg_name, - pascal_pkg, dvm_path::dvm_bin_dir()?.display(), pkg_name )) - .arg(&desktop_file) + .arg(&desktop_source) .spawn()? .wait() .await?; @@ -158,7 +157,15 @@ if [[ -f $USER_FLAGS_FILE ]]; then USER_FLAGS="$(cat $USER_FLAGS_FILE | sed 's/#.*//')" fi -exec "{}/{}" "$@" $USER_FLAGS +INSTALL_DIR="{}" +BIN_NAME="{}" +APP_DIR="$(find "$INSTALL_DIR" -maxdepth 1 -type d -name 'app-*' 2>/dev/null | sort -V | tail -n 1)" + +if [[ -n "$APP_DIR" && -x "$APP_DIR/$BIN_NAME" ]]; then + exec "$APP_DIR/$BIN_NAME" "$@" $USER_FLAGS +fi + +exec "$INSTALL_DIR/$BIN_NAME" "$@" $USER_FLAGS "#, pkg_name, install_dir.display(), @@ -183,28 +190,21 @@ exec "{}/{}" "$@" $USER_FLAGS // copy desktop file to .local/share/applications let local_apps_dir = dvm_path::home_dir()?.join(".local").join("share").join("applications"); - if Path::new(&desktop_file).exists() { - Command::new("install") - .arg("-Dm644") - .arg(&desktop_file) - .arg(&local_apps_dir) - .spawn()? - .wait() - .await?; + if desktop_source.exists() { + fs::create_dir_all(&local_apps_dir)?; + fs::copy( + &desktop_source, + local_apps_dir.join(format!("{}.desktop", pkg_name)), + )?; info!("installing desktop file"); } // copy icon to .local/share/icons let local_icons_dir = dvm_path::home_dir()?.join(".local").join("share").join("icons"); fs::create_dir_all(&local_icons_dir)?; - let icon_file = app_dir.join("discord.png"); - if Path::new(&icon_file).exists() { - Command::new("cp") - .arg(&icon_file) - .arg(local_icons_dir.join(format!("{}.png", pkg_name))) - .spawn()? - .wait() - .await?; + let icon_file = install_dir.join("discord.png"); + if icon_file.exists() { + fs::copy(&icon_file, local_icons_dir.join(format!("{}.png", pkg_name)))?; info!("installing icons"); }