Projektordner im ⚙︎-Dialog änderbar: Registry-Eintrag neu zuordnen, autoMemoryDirectory + Edit-Permission ziehen auf den neuen Root um; gesperrt bei laufender Session
This commit is contained in:
@@ -559,6 +559,53 @@ fn create_project_full_in(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Verlegt den Projektordner: Registry-Eintrag auf den neuen Pfad; Verweise
|
||||
/// auf den alten Root in der settings.json (autoMemoryDirectory,
|
||||
/// Edit-Permission) ziehen mit. Verschoben wird nichts — der neue Ordner
|
||||
/// muss existieren.
|
||||
fn set_project_dir_in(paths: &Paths, name: &str, dir: &str) -> Result<(), String> {
|
||||
check_name(name)?;
|
||||
let new_dir = expand_home(paths, dir);
|
||||
if !new_dir.is_dir() {
|
||||
return Err(format!("Ordner nicht gefunden: {}", new_dir.display()));
|
||||
}
|
||||
let mut reg = load_registry(paths)?;
|
||||
let old_dir = reg
|
||||
.get(name)
|
||||
.cloned()
|
||||
.ok_or_else(|| format!("Projekt nicht registriert: {name}"))?;
|
||||
if old_dir == new_dir {
|
||||
return Ok(());
|
||||
}
|
||||
reg.insert(name.to_string(), new_dir.clone());
|
||||
save_registry(paths, ®)?;
|
||||
|
||||
let sp = settings_path(&new_dir);
|
||||
if !sp.is_file() {
|
||||
return Ok(()); // importierte Projekte ohne settings.json
|
||||
}
|
||||
let old_c = contract_home(paths, &old_dir);
|
||||
let new_c = contract_home(paths, &new_dir);
|
||||
let raw = fs::read_to_string(&sp).map_err(|e| format!("{}: {e}", sp.display()))?;
|
||||
let mut v: serde_json::Value =
|
||||
serde_json::from_str(&raw).map_err(|e| format!("{}: {e}", sp.display()))?;
|
||||
if let Some(mem) = v["autoMemoryDirectory"].as_str() {
|
||||
if let Some(rest) = mem.strip_prefix(&old_c) {
|
||||
v["autoMemoryDirectory"] = serde_json::json!(format!("{new_c}{rest}"));
|
||||
}
|
||||
}
|
||||
if let Some(allow) = v["permissions"]["allow"].as_array_mut() {
|
||||
let old_edit = format!("Edit({old_c}/**)");
|
||||
for e in allow.iter_mut() {
|
||||
if e.as_str() == Some(&old_edit) {
|
||||
*e = serde_json::json!(format!("Edit({new_c}/**)"));
|
||||
}
|
||||
}
|
||||
}
|
||||
let raw = serde_json::to_string_pretty(&v).map_err(|e| e.to_string())?;
|
||||
fs::write(&sp, raw + "\n").map_err(|e| format!("{}: {e}", sp.display()))
|
||||
}
|
||||
|
||||
/// Nimmt einen bestehenden Ordner als Projekt auf; der Name ist der Ordnername.
|
||||
fn add_project_in(paths: &Paths, path: &str) -> Result<(), String> {
|
||||
let dir = expand_home(paths, path);
|
||||
@@ -1544,6 +1591,15 @@ fn remove_project(name: String) -> Result<(), String> {
|
||||
unregister_project(&Paths::real(), &name)
|
||||
}
|
||||
|
||||
/// Projektordner neu zuordnen; bei laufender Session gesperrt.
|
||||
#[tauri::command]
|
||||
fn set_project_dir(project: String, dir: String) -> Result<(), String> {
|
||||
if is_running(&project) {
|
||||
return Err(format!("{project} läuft noch — erst beenden"));
|
||||
}
|
||||
set_project_dir_in(&Paths::real(), &project, &dir)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn add_work_dir(project: String, dir: String) -> Result<(), String> {
|
||||
add_work_dir_in(&Paths::real(), &project, &dir)
|
||||
@@ -1906,6 +1962,7 @@ fn main_builder() -> tauri::Builder<tauri::Wry> {
|
||||
remove_project,
|
||||
delete_project,
|
||||
project_work_dirs,
|
||||
set_project_dir,
|
||||
add_work_dir,
|
||||
remove_work_dir,
|
||||
list_pools,
|
||||
@@ -2753,6 +2810,24 @@ mod tests {
|
||||
assert!(p.home.join("projects/extra").is_dir());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn projektordner_verlegen() {
|
||||
let p = tmp_paths();
|
||||
create_project_full_in(&p, "proj", None, None, None, false, TerminalConfig::default(), false)
|
||||
.unwrap();
|
||||
// Nutzer hat den Ordner selbst verschoben; die App ordnet nur neu zu.
|
||||
let new_dir = p.home.join("elsewhere").join("proj");
|
||||
fs::create_dir_all(p.home.join("elsewhere")).unwrap();
|
||||
fs::rename(p.projects_dir().join("proj"), &new_dir).unwrap();
|
||||
set_project_dir_in(&p, "proj", &new_dir.to_string_lossy()).unwrap();
|
||||
|
||||
assert_eq!(project_dir(&p, "proj").unwrap(), new_dir);
|
||||
let raw = fs::read_to_string(settings_path(&new_dir)).unwrap();
|
||||
assert!(raw.contains("~/elsewhere/proj/memory"));
|
||||
assert!(raw.contains("Edit(~/elsewhere/proj/**)"));
|
||||
assert!(!raw.contains("claude-projects/proj"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn projekt_loeschen_unbekannt_scheitert() {
|
||||
let p = tmp_paths();
|
||||
|
||||
Reference in New Issue
Block a user