[yabridgectl] Normalize symlinks for plugin counts

Now this should actually be correct with partially overlapping plugin
directories when symlinks were used.
This commit is contained in:
Robbert van der Helm
2021-07-05 17:51:06 +02:00
parent a06d0bc515
commit bf84057044
3 changed files with 33 additions and 6 deletions
+3 -2
View File
@@ -96,8 +96,9 @@ Versioning](https://semver.org/spec/v2.0.0.html).
because yabridgectl would try to run the 64-bit `yabridge-host.exe` in that
prefix.
- Fixed incorrect new and total plugin counts. These counts are now always
correct, even when using multiple versions of the same VST3 plugin or when a
plugin directory contains a symlink to another plugin directory.
correct, even when using multiple versions of the same VST3 plugin or when
multiple plugin directories overlap because parts of the directory were
symlinked to another plugin directory.
- Aside from pruning only unmanaged VST3 bundles in `~/.vst3/yabridge`, yabridge
will now also prompt you to prune unmanaged files within a VST3 bundle. This
makes it easy to switch from the 64-bit version of a plugin to the 32-bit
+14 -4
View File
@@ -231,6 +231,9 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
// this makes everything much easier since we'll have to deal with things like a plugin
// directory A containing a symlink to plugin directory B, as well as VST3 plugisn that come in
// both x86 and x86_64 flavours.
// Paths added to this and to the `new_plugins` set below should be normalized with
// `utils::normalize_path()` so that the reported numbers are still correct when encountering
// overlapping symlinked paths.
let mut managed_plugins: HashSet<PathBuf> = HashSet::new();
// The plugins we created a new copy of `libyabridge-{vst2,vst3}.so` for. We don't touch these
// files if they're already up to date to prevent hosts from unnecessarily rescanning the
@@ -265,6 +268,7 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
path: plugin_path, ..
}) => {
let target_path = plugin_path.with_extension("so");
let normalized_target_path = utils::normalize_path(&target_path);
// Since we skip some files, we'll also keep track of how many new file we've
// actually set up
@@ -275,9 +279,9 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
Some(libyabridge_vst2_hash),
&target_path,
)? {
new_plugins.insert(target_path.clone());
new_plugins.insert(normalized_target_path.clone());
}
managed_plugins.insert(target_path);
managed_plugins.insert(normalized_target_path);
plugin_path.clone()
}
@@ -292,6 +296,8 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
let target_bundle_home = module.target_bundle_home();
let target_native_module_path = module.target_native_module_path(Some(&files));
let target_windows_module_path = module.target_windows_module_path();
let normalized_native_module_path =
utils::normalize_path(&target_native_module_path);
// 32-bit and 64-bit versions of the plugin can live inside of the same bundle),
// but it's not possible to use the exact same plugin from multiple Wine
@@ -327,9 +333,13 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
libyabridge_vst3_hash,
&target_native_module_path,
)? {
new_plugins.insert(target_native_module_path.clone());
// We're counting the native `.so` files and not the Windows VST3 plugins
// because even though the 32-bit and 64-bit versions of a plugin are
// technically separate plugins, we can only use one at a time anyways
// because of how these bundles work
new_plugins.insert(normalized_native_module_path.clone());
}
managed_plugins.insert(target_native_module_path.clone());
managed_plugins.insert(normalized_native_module_path.clone());
managed_vst3_bundle_files.insert(target_native_module_path);
// We'll then symlink the Windows VST3 module to that bundle to create a merged
+16
View File
@@ -176,6 +176,22 @@ pub fn hash_file(file: &Path) -> Result<i64> {
Ok(hasher.finish() as i64)
}
/// Resolve symlinks in a path, like the `realpath` coreutil, but don't throw any errors of `path`
/// does not exist, unlike the `realpath` libc function.
///
/// This is used to resolve symlinked directories in the syncing process so the plugin counts are
/// correct even when one plugin directory contains a symlink to another plugin directory.
pub fn normalize_path(path: &Path) -> PathBuf {
for prefix in path.ancestors() {
// If part of `path`s prefix exists, then we'll try to resolve symlinks there
if let Ok(normalized_prefix) = fs::canonicalize(&prefix) {
return normalized_prefix.join(path.strip_prefix(prefix).unwrap());
}
}
path.to_owned()
}
/// Verify that `yabridge-host.exe` can be found when yabridge is run in a host launched from the
/// GUI. We do this by launching a login shell, appending `~/.local/share/yabridge` to the login
/// shell's search path since that's what yabridge also does, and then making the the file can be