Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion varManager_backend/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1893,6 +1893,7 @@ pub async fn list_packswitch(

let addon_path = crate::infra::paths::addon_packages_dir(&vampath);
let link_root = addon_path.join(crate::infra::paths::INSTALL_LINK_DIR);
let switch_root = crate::infra::paths::addon_switch_root(&vampath);
let current = if let Ok(target) = crate::infra::winfs::read_link_target(&link_root) {
let resolved = if target.is_absolute() {
target
Expand All @@ -1902,7 +1903,6 @@ pub async fn list_packswitch(
.unwrap_or(&addon_path)
.join(target)
};
let switch_root = crate::infra::paths::addon_switch_root(&vampath);
if resolved.starts_with(&switch_root) {
resolved
.parent()
Expand All @@ -1913,6 +1913,24 @@ pub async fn list_packswitch(
} else {
"default".to_string()
}
} else if let Ok(target) = crate::infra::winfs::read_link_target(&addon_path) {
let resolved = if target.is_absolute() {
target
} else {
addon_path
.parent()
.unwrap_or(&addon_path)
.join(target)
};
if resolved.starts_with(&switch_root) {
resolved
.file_name()
.and_then(|s| s.to_str())
.unwrap_or("default")
.to_string()
} else {
"default".to_string()
}
} else {
"default".to_string()
};
Expand Down
48 changes: 46 additions & 2 deletions varManager_backend/src/jobs/packswitch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,10 @@ fn set_switch_blocking(
fs::create_dir_all(&target).map_err(|err| err.to_string())?;

let addon_path = addon_packages_dir(&vampath);
fs::create_dir_all(&addon_path).map_err(|err| err.to_string())?;
let addon_was_symlink = ensure_addonpackages_dir(&addon_path, reporter)?;

let managed_dirs = collect_managed_dirs();
if managed_dirs_have_real_vars(&addon_path, &managed_dirs) {
if !addon_was_symlink && managed_dirs_have_real_vars(&addon_path, &managed_dirs) {
reporter.log(format!(
"Managed link folders contain real var files; update DB required: {}",
addon_path.display()
Expand Down Expand Up @@ -252,6 +252,28 @@ fn collect_managed_dirs() -> BTreeSet<String> {
dirs
}

fn ensure_addonpackages_dir(addon_path: &Path, reporter: &JobReporter) -> Result<bool, String> {
if fs_util::is_symlink(addon_path) {
reporter.log(format!(
"AddonPackages is a symlink; migrating to folder-based packswitch: {}",
addon_path.display()
));
if fs::remove_file(addon_path).is_err() {
fs::remove_dir_all(addon_path).map_err(|err| err.to_string())?;
}
fs::create_dir_all(addon_path).map_err(|err| err.to_string())?;
return Ok(true);
}
if addon_path.exists() && !addon_path.is_dir() {
return Err(format!(
"AddonPackages is not a directory: {}",
addon_path.display()
));
}
fs::create_dir_all(addon_path).map_err(|err| err.to_string())?;
Ok(false)
}

fn managed_dirs_have_real_vars(addon_path: &Path, managed_dirs: &BTreeSet<String>) -> bool {
for dir_name in managed_dirs {
let path = addon_path.join(dir_name);
Expand Down Expand Up @@ -601,4 +623,26 @@ mod tests {

let _ = fs::remove_dir_all(&root);
}

#[test]
fn migrate_addonpackages_symlink_to_directory() {
if !symlink_supported() {
return;
}
let root = make_temp_dir("packswitch_migrate_symlink");
let addon_path = root.join("AddonPackages");
let target = root.join("legacy_target");
fs::create_dir_all(&target).unwrap();
winfs::create_symlink_dir(&addon_path, &target).unwrap();

let (tx, _rx) = create_job_channel();
let reporter = JobReporter::new(1, tx);
let was_symlink = ensure_addonpackages_dir(&addon_path, &reporter).unwrap();

assert!(was_symlink);
assert!(addon_path.exists());
assert!(!fs_util::is_symlink(&addon_path));

let _ = fs::remove_dir_all(&root);
}
}
1 change: 1 addition & 0 deletions varmanager_flutter/lib/features/home/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,7 @@ class _HomePageState extends ConsumerState<HomePage> {
final result = await _runJob('update_db');
ref.invalidate(varsListProvider);
await _showUpdateDbSummary(result);
await _loadPackSwitches();
},
icon: const Icon(Icons.sync),
label: Text(l10n.updateDbLabel),
Expand Down