mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-09 20:29:10 +02:00
[yabridgectl] Allow removing orphan VST3 modules
This commit is contained in:
@@ -18,10 +18,11 @@
|
|||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
use std::collections::BTreeSet;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use crate::config::{Config, InstallationMethod, YabridgeFiles};
|
use crate::config::{yabridge_vst3_home, Config, InstallationMethod, YabridgeFiles};
|
||||||
use crate::files;
|
use crate::files;
|
||||||
use crate::files::NativeFile;
|
use crate::files::NativeFile;
|
||||||
use crate::utils;
|
use crate::utils;
|
||||||
@@ -193,16 +194,16 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
|
|||||||
let mut num_new = 0;
|
let mut num_new = 0;
|
||||||
// The files we skipped during the scan because they turned out to not be plugins
|
// The files we skipped during the scan because they turned out to not be plugins
|
||||||
let mut skipped_dll_files: Vec<PathBuf> = Vec::new();
|
let mut skipped_dll_files: Vec<PathBuf> = Vec::new();
|
||||||
// `.so` files we found during scanning that didn't have a corresponding copy or symlink of
|
// `.so` files and unused VST3 modules we found during scanning that didn't have a corresponding
|
||||||
// `libyabridge-vst2.so`
|
// copy or symlink of `libyabridge-vst2.so`
|
||||||
let mut orphan_vst2_so_files: Vec<NativeFile> = Vec::new();
|
let mut orphan_files: Vec<NativeFile> = Vec::new();
|
||||||
// All the VST3 modules we have set up yabridge for. We need this to detect leftover VST3
|
// All the VST3 modules we have set up yabridge for. We need this to detect leftover VST3
|
||||||
// modules in `~/.vst3/yabridge`.
|
// modules in `~/.vst3/yabridge`.
|
||||||
let mut yabridge_vst3_bundles: Vec<PathBuf> = Vec::new();
|
let mut yabridge_vst3_bundles: BTreeSet<PathBuf> = BTreeSet::new();
|
||||||
for (path, search_results) in results {
|
for (path, search_results) in results {
|
||||||
num_installed += search_results.vst2_files.len();
|
num_installed += search_results.vst2_files.len();
|
||||||
num_installed += search_results.vst3_modules.len();
|
num_installed += search_results.vst3_modules.len();
|
||||||
orphan_vst2_so_files.extend(search_results.vst2_orphans().into_iter().cloned());
|
orphan_files.extend(search_results.vst2_orphans().into_iter().cloned());
|
||||||
yabridge_vst3_bundles.extend(
|
yabridge_vst3_bundles.extend(
|
||||||
search_results
|
search_results
|
||||||
.vst3_modules
|
.vst3_modules
|
||||||
@@ -214,6 +215,8 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
|
|||||||
if options.verbose {
|
if options.verbose {
|
||||||
println!("{}:", path.display());
|
println!("{}:", path.display());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We'll set up the copies or symlinks for VST2 plugins
|
||||||
for plugin in search_results.vst2_files {
|
for plugin in search_results.vst2_files {
|
||||||
let target_path = plugin.with_extension("so");
|
let target_path = plugin.with_extension("so");
|
||||||
|
|
||||||
@@ -233,6 +236,9 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
|
|||||||
println!(" {}", plugin.display());
|
println!(" {}", plugin.display());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// And then create merged bundles for the VST3 plugins:
|
||||||
|
// https://steinbergmedia.github.io/vst3_doc/vstinterfaces/vst3loc.html#mergedbundles
|
||||||
if let Some(libyabridge_vst3_hash) = libyabridge_vst3_hash {
|
if let Some(libyabridge_vst3_hash) = libyabridge_vst3_hash {
|
||||||
for module in search_results.vst3_modules {
|
for module in search_results.vst3_modules {
|
||||||
let native_module_path = module.yabridge_native_module_path();
|
let native_module_path = module.yabridge_native_module_path();
|
||||||
@@ -269,6 +275,7 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.verbose {
|
if options.verbose {
|
||||||
println!();
|
println!();
|
||||||
}
|
}
|
||||||
@@ -284,29 +291,50 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
|
|||||||
println!();
|
println!();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove leftover files for VST3 plugins
|
if let Ok(dirs) = fs::read_dir(yabridge_vst3_home()) {
|
||||||
|
orphan_files.extend(
|
||||||
|
dirs.filter_map(|entry| entry.ok())
|
||||||
|
.map(|entry| entry.path())
|
||||||
|
.filter_map(|path| {
|
||||||
|
// Add all files and directories in `~/.vst3/yabridge` to `orphan_files` if they
|
||||||
|
// are not a VST3 module we just created
|
||||||
|
if !yabridge_vst3_bundles.contains(&path) {
|
||||||
|
utils::get_file_type(path)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Always warn about leftover files since those might cause warnings or errors when a VST host
|
// Always warn about leftover files since those might cause warnings or errors when a VST host
|
||||||
// tries to load them
|
// tries to load them
|
||||||
if !orphan_vst2_so_files.is_empty() {
|
if !orphan_files.is_empty() {
|
||||||
|
let leftover_files_str = if orphan_files.len() == 1 {
|
||||||
|
format!("{} leftover file", orphan_files.len())
|
||||||
|
} else {
|
||||||
|
format!("{} leftover files", orphan_files.len())
|
||||||
|
};
|
||||||
if options.prune {
|
if options.prune {
|
||||||
println!(
|
println!("Removing {}:", leftover_files_str);
|
||||||
"Removing {} leftover .so files:",
|
|
||||||
orphan_vst2_so_files.len()
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
println!(
|
println!(
|
||||||
"Found {} leftover .so files, rerun with the '--prune' option to remove them:",
|
"Found {}, rerun with the '--prune' option to remove them:",
|
||||||
orphan_vst2_so_files.len()
|
leftover_files_str
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for file in orphan_vst2_so_files {
|
for file in orphan_files {
|
||||||
let path = file.path();
|
println!("- {}", file.path().display());
|
||||||
|
|
||||||
println!("- {}", path.display());
|
|
||||||
if options.prune {
|
if options.prune {
|
||||||
utils::remove_file(path)?;
|
match file {
|
||||||
|
NativeFile::Regular(path) | NativeFile::Symlink(path) => {
|
||||||
|
utils::remove_file(path)?;
|
||||||
|
}
|
||||||
|
NativeFile::Directory(path) => {
|
||||||
|
utils::remove_dir_all(path)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ impl SearchResults {
|
|||||||
// because they are not in any of the directories we're indexing.
|
// because they are not in any of the directories we're indexing.
|
||||||
installation_status.extend(self.vst3_modules.iter().map(|module| {
|
installation_status.extend(self.vst3_modules.iter().map(|module| {
|
||||||
let module_path = module.yabridge_native_module_path();
|
let module_path = module.yabridge_native_module_path();
|
||||||
let install_type = get_file_type(&module_path);
|
let install_type = get_file_type(module_path.clone());
|
||||||
(module_path, install_type)
|
(module_path, install_type)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -372,7 +372,7 @@ impl SearchIndex {
|
|||||||
reconstructed_path.push(architecture.vst_arch());
|
reconstructed_path.push(architecture.vst_arch());
|
||||||
reconstructed_path.push(module_name);
|
reconstructed_path.push(module_name);
|
||||||
|
|
||||||
return reconstructed_path.exists();
|
reconstructed_path.exists()
|
||||||
})
|
})
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ use std::fs;
|
|||||||
use std::hash::Hasher;
|
use std::hash::Hasher;
|
||||||
use std::os::unix::fs as unix_fs;
|
use std::os::unix::fs as unix_fs;
|
||||||
use std::os::unix::process::CommandExt;
|
use std::os::unix::process::CommandExt;
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
use textwrap::Wrapper;
|
use textwrap::Wrapper;
|
||||||
|
|
||||||
@@ -59,6 +59,13 @@ pub fn create_dir_all<P: AsRef<Path>>(path: P) -> Result<()> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wrapper around [`std::fs::remove_dir_all()`](std::fs::remove_dir_all) with a human readable
|
||||||
|
/// error message.
|
||||||
|
pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> Result<()> {
|
||||||
|
fs::remove_dir_all(&path)
|
||||||
|
.with_context(|| format!("Could not remove directory '{}'", path.as_ref().display()))
|
||||||
|
}
|
||||||
|
|
||||||
/// Wrapper around [`std::fs::remove_file()`](std::fs::remove_file) with a human readable error
|
/// Wrapper around [`std::fs::remove_file()`](std::fs::remove_file) with a human readable error
|
||||||
/// message.
|
/// message.
|
||||||
pub fn remove_file<P: AsRef<Path>>(path: P) -> Result<()> {
|
pub fn remove_file<P: AsRef<Path>>(path: P) -> Result<()> {
|
||||||
@@ -79,15 +86,11 @@ pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the type of a file, if it exists.
|
/// Get the type of a file, if it exists.
|
||||||
pub fn get_file_type(path: &Path) -> Option<NativeFile> {
|
pub fn get_file_type(path: PathBuf) -> Option<NativeFile> {
|
||||||
match path.metadata() {
|
match path.metadata() {
|
||||||
Ok(metadata) if metadata.file_type().is_symlink() => {
|
Ok(metadata) if metadata.file_type().is_symlink() => Some(NativeFile::Symlink(path)),
|
||||||
Some(NativeFile::Symlink(path.to_owned()))
|
Ok(metadata) if metadata.file_type().is_dir() => Some(NativeFile::Directory(path)),
|
||||||
}
|
Ok(_) => Some(NativeFile::Regular(path)),
|
||||||
Ok(metadata) if metadata.file_type().is_dir() => {
|
|
||||||
Some(NativeFile::Directory(path.to_owned()))
|
|
||||||
}
|
|
||||||
Ok(_) => Some(NativeFile::Regular(path.to_owned())),
|
|
||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user