|
1 | | -use crate::types::ProviderId; |
| 1 | +use crate::types::{str_field, ProviderId}; |
2 | 2 | use anyhow::{anyhow, Result}; |
3 | 3 | use serde::{Deserialize, Serialize}; |
4 | 4 | use serde_json::Value; |
@@ -275,16 +275,33 @@ pub fn import_archive(path: &Path, project_dir: Option<&Path>) -> Result<PathBuf |
275 | 275 | archive.source_provider.id(), |
276 | 276 | archive.title |
277 | 277 | )); |
278 | | - let mut target = dir.join(format!("{base}.{ARCHIVE_EXT}")); |
279 | | - let mut n = 2usize; |
280 | | - while target.exists() { |
281 | | - target = dir.join(format!("{base}-{n}.{ARCHIVE_EXT}")); |
282 | | - n += 1; |
283 | | - } |
| 278 | + let target = unique_path(&dir, &base, ARCHIVE_EXT); |
284 | 279 | fs::write(&target, serde_json::to_string_pretty(&archive)?)?; |
285 | 280 | Ok(target) |
286 | 281 | } |
287 | 282 |
|
| 283 | +fn unique_path(dir: &Path, stem: &str, ext: &str) -> PathBuf { |
| 284 | + let first = if ext.is_empty() { |
| 285 | + dir.join(stem) |
| 286 | + } else { |
| 287 | + dir.join(format!("{stem}.{ext}")) |
| 288 | + }; |
| 289 | + if !first.exists() { |
| 290 | + return first; |
| 291 | + } |
| 292 | + for n in 2.. { |
| 293 | + let candidate = if ext.is_empty() { |
| 294 | + dir.join(format!("{stem}-{n}")) |
| 295 | + } else { |
| 296 | + dir.join(format!("{stem}-{n}.{ext}")) |
| 297 | + }; |
| 298 | + if !candidate.exists() { |
| 299 | + return candidate; |
| 300 | + } |
| 301 | + } |
| 302 | + unreachable!() |
| 303 | +} |
| 304 | + |
288 | 305 | pub fn import_zip(path: &Path, project_dir: Option<&Path>) -> Result<BatchReport> { |
289 | 306 | let file = File::open(path)?; |
290 | 307 | let mut zip = ZipArchive::new(file)?; |
@@ -318,12 +335,7 @@ pub fn import_zip(path: &Path, project_dir: Option<&Path>) -> Result<BatchReport |
318 | 335 | archive.source_provider.id(), |
319 | 336 | archive.title |
320 | 337 | )); |
321 | | - let mut target = dir.join(format!("{base}.{ARCHIVE_EXT}")); |
322 | | - let mut n = 2usize; |
323 | | - while target.exists() { |
324 | | - target = dir.join(format!("{base}-{n}.{ARCHIVE_EXT}")); |
325 | | - n += 1; |
326 | | - } |
| 338 | + let target = unique_path(&dir, &base, ARCHIVE_EXT); |
327 | 339 | fs::write(&target, serde_json::to_string_pretty(&archive)?)?; |
328 | 340 | report.ok += 1; |
329 | 341 | } |
@@ -351,12 +363,7 @@ pub fn soft_delete(session: &ChatSession, workspace: &Path) -> Result<()> { |
351 | 363 | .extension() |
352 | 364 | .and_then(|e| e.to_str()) |
353 | 365 | .unwrap_or("chat"); |
354 | | - let mut target = trash_dir.join(format!("{stem}.{ext}")); |
355 | | - let mut n = 2usize; |
356 | | - while target.exists() { |
357 | | - target = trash_dir.join(format!("{stem}-{n}.{ext}")); |
358 | | - n += 1; |
359 | | - } |
| 366 | + let target = unique_path(&trash_dir, &stem, ext); |
360 | 367 | move_path(source, &target)?; |
361 | 368 | let manifest = DeleteManifest { |
362 | 369 | schema_version: ARCHIVE_VERSION, |
@@ -390,12 +397,7 @@ fn soft_delete_kiro_session(session: &ChatSession) -> Result<()> { |
390 | 397 | let trash_dir = trash_dir().join(session.provider.id()); |
391 | 398 | fs::create_dir_all(&trash_dir)?; |
392 | 399 | let stem = safe_file_stem(&format!("{}-{}", session.id, session.title)); |
393 | | - let mut target = trash_dir.join(&stem); |
394 | | - let mut n = 2usize; |
395 | | - while target.exists() { |
396 | | - target = trash_dir.join(format!("{stem}-{n}")); |
397 | | - n += 1; |
398 | | - } |
| 400 | + let target = unique_path(&trash_dir, &stem, ""); |
399 | 401 | fs::create_dir_all(&target)?; |
400 | 402 | let base = meta_path.with_extension(""); |
401 | 403 | for ext in ["json", "jsonl", "lock"] { |
@@ -1177,11 +1179,6 @@ fn project_label_from_path(provider: ChatProvider, _root: &Path, path: &Path) -> |
1177 | 1179 | } |
1178 | 1180 | } |
1179 | 1181 |
|
1180 | | -fn str_field<'a>(value: &'a Value, keys: &[&str]) -> Option<&'a str> { |
1181 | | - keys.iter() |
1182 | | - .find_map(|key| value.get(*key).and_then(Value::as_str)) |
1183 | | -} |
1184 | | - |
1185 | 1182 | fn first_string(value: Option<&Value>) -> Option<&str> { |
1186 | 1183 | value |
1187 | 1184 | .and_then(Value::as_array) |
|
0 commit comments