Skip to content

Commit a4d739d

Browse files
5858
authored andcommitted
Align uninstall log cleanup with actual logs directory
1 parent 7954d02 commit a4d739d

2 files changed

Lines changed: 149 additions & 77 deletions

File tree

src/cortex-cli/src/logs_cmd.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
99
use anyhow::Result;
1010
use clap::Parser;
11+
use cortex_common::dirs::AppDirs;
1112
use serde::Serialize;
1213
use std::path::PathBuf;
1314

@@ -58,11 +59,11 @@ struct LogFileInfo {
5859

5960
/// Get the logs directory.
6061
fn get_logs_dir() -> PathBuf {
61-
dirs::cache_dir()
62-
.map(|c| c.join("cortex").join("logs"))
62+
AppDirs::new()
63+
.map(|dirs| dirs.logs_dir())
6364
.unwrap_or_else(|| {
6465
dirs::home_dir()
65-
.map(|h| h.join(".cache").join("cortex").join("logs"))
66+
.map(|h| h.join(".cortex").join("cache").join("logs"))
6667
.unwrap_or_else(|| PathBuf::from(".cache/cortex/logs"))
6768
})
6869
}

src/cortex-cli/src/uninstall_cmd.rs

Lines changed: 145 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use crate::styled_output::{print_info, print_warning};
1313
use anyhow::{Context, Result, bail};
1414
use clap::Parser;
15+
use cortex_common::dirs::{AppDirs, HOME_DIR_NAME, LEGACY_XDG_NAME};
1516
use std::collections::HashMap;
1617
use std::fs;
1718
use std::path::{Path, PathBuf};
@@ -388,12 +389,22 @@ fn collect_binary_locations(home_dir: &Path) -> Result<Vec<RemovalItem>> {
388389

389390
/// Collect items from the ~/.cortex directory.
390391
fn collect_cortex_home_items(home_dir: &Path) -> Result<Vec<RemovalItem>> {
391-
let mut items = Vec::new();
392-
let cortex_home = home_dir.join(".cortex");
392+
let app_dirs = AppDirs::new().unwrap_or_else(|| {
393+
let cortex_home = home_dir.join(HOME_DIR_NAME);
394+
AppDirs {
395+
config_dir: cortex_home.clone(),
396+
data_dir: cortex_home.clone(),
397+
cache_dir: cortex_home.join("cache"),
398+
legacy_xdg_home: home_dir.join(LEGACY_XDG_NAME),
399+
}
400+
});
393401

394-
if !cortex_home.exists() {
395-
return Ok(items);
396-
}
402+
collect_cortex_home_items_from_dirs(&app_dirs)
403+
}
404+
405+
fn collect_cortex_home_items_from_dirs(app_dirs: &AppDirs) -> Result<Vec<RemovalItem>> {
406+
let mut items = Vec::new();
407+
let cortex_home = &app_dirs.config_dir;
397408

398409
// Configuration files
399410
let config_files = [
@@ -402,33 +413,83 @@ fn collect_cortex_home_items(home_dir: &Path) -> Result<Vec<RemovalItem>> {
402413
("auth.json", "OAuth tokens"),
403414
];
404415

405-
for (file, desc) in config_files {
406-
let path = cortex_home.join(file);
407-
if path.exists() {
416+
if cortex_home.exists() {
417+
for (file, desc) in config_files {
418+
let path = cortex_home.join(file);
419+
if path.exists() {
420+
items.push(RemovalItem {
421+
path: path.clone(),
422+
description: desc.to_string(),
423+
size: get_file_size(&path),
424+
requires_sudo: false,
425+
category: RemovalCategory::Config,
426+
});
427+
}
428+
}
429+
430+
// Session data directory
431+
let sessions_dir = cortex_home.join("sessions");
432+
if sessions_dir.exists() {
408433
items.push(RemovalItem {
409-
path: path.clone(),
410-
description: desc.to_string(),
411-
size: get_file_size(&path),
434+
path: sessions_dir.clone(),
435+
description: "Session history and data".to_string(),
436+
size: get_dir_size(&sessions_dir),
437+
requires_sudo: false,
438+
category: RemovalCategory::Data,
439+
});
440+
}
441+
442+
// Plugins directory
443+
let plugins_dir = cortex_home.join("plugins");
444+
if plugins_dir.exists() {
445+
items.push(RemovalItem {
446+
path: plugins_dir.clone(),
447+
description: "Installed plugins".to_string(),
448+
size: get_dir_size(&plugins_dir),
449+
requires_sudo: false,
450+
category: RemovalCategory::Plugins,
451+
});
452+
}
453+
454+
// Skills directory
455+
let skills_dir = cortex_home.join("skills");
456+
if skills_dir.exists() {
457+
items.push(RemovalItem {
458+
path: skills_dir.clone(),
459+
description: "Custom skills".to_string(),
460+
size: get_dir_size(&skills_dir),
461+
requires_sudo: false,
462+
category: RemovalCategory::Plugins,
463+
});
464+
}
465+
466+
// MCP servers directory
467+
let mcp_dir = cortex_home.join("mcp");
468+
if mcp_dir.exists() {
469+
items.push(RemovalItem {
470+
path: mcp_dir.clone(),
471+
description: "MCP server configurations".to_string(),
472+
size: get_dir_size(&mcp_dir),
412473
requires_sudo: false,
413474
category: RemovalCategory::Config,
414475
});
415476
}
416-
}
417477

418-
// Session data directory
419-
let sessions_dir = cortex_home.join("sessions");
420-
if sessions_dir.exists() {
421-
items.push(RemovalItem {
422-
path: sessions_dir.clone(),
423-
description: "Session history and data".to_string(),
424-
size: get_dir_size(&sessions_dir),
425-
requires_sudo: false,
426-
category: RemovalCategory::Data,
427-
});
478+
// Agents directory
479+
let agents_dir = cortex_home.join("agents");
480+
if agents_dir.exists() {
481+
items.push(RemovalItem {
482+
path: agents_dir.clone(),
483+
description: "Custom agents".to_string(),
484+
size: get_dir_size(&agents_dir),
485+
requires_sudo: false,
486+
category: RemovalCategory::Plugins,
487+
});
488+
}
428489
}
429490

430-
// Logs directory
431-
let logs_dir = cortex_home.join("logs");
491+
// Actual logs directory used by `cortex logs`.
492+
let logs_dir = app_dirs.logs_dir();
432493
if logs_dir.exists() {
433494
items.push(RemovalItem {
434495
path: logs_dir.clone(),
@@ -439,56 +500,8 @@ fn collect_cortex_home_items(home_dir: &Path) -> Result<Vec<RemovalItem>> {
439500
});
440501
}
441502

442-
// Plugins directory
443-
let plugins_dir = cortex_home.join("plugins");
444-
if plugins_dir.exists() {
445-
items.push(RemovalItem {
446-
path: plugins_dir.clone(),
447-
description: "Installed plugins".to_string(),
448-
size: get_dir_size(&plugins_dir),
449-
requires_sudo: false,
450-
category: RemovalCategory::Plugins,
451-
});
452-
}
453-
454-
// Skills directory
455-
let skills_dir = cortex_home.join("skills");
456-
if skills_dir.exists() {
457-
items.push(RemovalItem {
458-
path: skills_dir.clone(),
459-
description: "Custom skills".to_string(),
460-
size: get_dir_size(&skills_dir),
461-
requires_sudo: false,
462-
category: RemovalCategory::Plugins,
463-
});
464-
}
465-
466-
// MCP servers directory
467-
let mcp_dir = cortex_home.join("mcp");
468-
if mcp_dir.exists() {
469-
items.push(RemovalItem {
470-
path: mcp_dir.clone(),
471-
description: "MCP server configurations".to_string(),
472-
size: get_dir_size(&mcp_dir),
473-
requires_sudo: false,
474-
category: RemovalCategory::Config,
475-
});
476-
}
477-
478-
// Agents directory
479-
let agents_dir = cortex_home.join("agents");
480-
if agents_dir.exists() {
481-
items.push(RemovalItem {
482-
path: agents_dir.clone(),
483-
description: "Custom agents".to_string(),
484-
size: get_dir_size(&agents_dir),
485-
requires_sudo: false,
486-
category: RemovalCategory::Plugins,
487-
});
488-
}
489-
490503
// Cache directory
491-
let cache_dir = cortex_home.join("cache");
504+
let cache_dir = app_dirs.cache_dir.clone();
492505
if cache_dir.exists() {
493506
items.push(RemovalItem {
494507
path: cache_dir.clone(),
@@ -517,7 +530,7 @@ fn collect_cortex_home_items(home_dir: &Path) -> Result<Vec<RemovalItem>> {
517530
} else {
518531
// Add the parent directory itself at the end (to be removed after contents)
519532
items.push(RemovalItem {
520-
path: cortex_home,
533+
path: cortex_home.clone(),
521534
description: "Cortex home directory (if empty)".to_string(),
522535
size: 0,
523536
requires_sudo: false,
@@ -926,6 +939,7 @@ fn clean_rc_file(path: &Path, patterns: &[&str]) -> Result<()> {
926939
#[cfg(test)]
927940
mod tests {
928941
use super::*;
942+
use tempfile::TempDir;
929943

930944
#[test]
931945
fn test_format_size() {
@@ -976,4 +990,61 @@ mod tests {
976990
| InstallMethod::Unknown => {}
977991
}
978992
}
993+
994+
#[test]
995+
fn test_collect_cortex_home_items_uses_actual_cache_logs_dir() {
996+
let temp = TempDir::new().unwrap();
997+
let config_dir = temp.path().join("config");
998+
let cache_dir = temp.path().join("cache");
999+
let logs_dir = cache_dir.join("logs");
1000+
1001+
fs::create_dir_all(&config_dir).unwrap();
1002+
fs::create_dir_all(&logs_dir).unwrap();
1003+
fs::write(logs_dir.join("debug.log"), "test log").unwrap();
1004+
1005+
let app_dirs = AppDirs {
1006+
config_dir: config_dir.clone(),
1007+
data_dir: config_dir.clone(),
1008+
cache_dir: cache_dir.clone(),
1009+
legacy_xdg_home: temp.path().join("legacy"),
1010+
};
1011+
1012+
let items = collect_cortex_home_items_from_dirs(&app_dirs).unwrap();
1013+
1014+
assert!(
1015+
items.iter().any(|item| item.path == logs_dir),
1016+
"expected uninstall items to include the real cache logs directory"
1017+
);
1018+
assert!(
1019+
!items
1020+
.iter()
1021+
.any(|item| item.path == config_dir.join("logs")),
1022+
"uninstall should not look for logs under the config directory"
1023+
);
1024+
}
1025+
1026+
#[test]
1027+
fn test_collect_cortex_home_items_keeps_cache_logs_without_config_dir() {
1028+
let temp = TempDir::new().unwrap();
1029+
let config_dir = temp.path().join("config");
1030+
let cache_dir = temp.path().join("cache");
1031+
let logs_dir = cache_dir.join("logs");
1032+
1033+
fs::create_dir_all(&logs_dir).unwrap();
1034+
fs::write(logs_dir.join("debug.log"), "test log").unwrap();
1035+
1036+
let app_dirs = AppDirs {
1037+
config_dir,
1038+
data_dir: temp.path().join("data"),
1039+
cache_dir: cache_dir.clone(),
1040+
legacy_xdg_home: temp.path().join("legacy"),
1041+
};
1042+
1043+
let items = collect_cortex_home_items_from_dirs(&app_dirs).unwrap();
1044+
1045+
assert!(
1046+
items.iter().any(|item| item.path == logs_dir),
1047+
"cache logs should still be removable even if the config dir is absent"
1048+
);
1049+
}
9791050
}

0 commit comments

Comments
 (0)