feat(recover): recover a selection of folders relative to each marked folder
A marked folder a/b/Projeto is recreated as Projeto/... with everything
inside it; single marked files go to the destination root and unmarked
files inside a marked folder are left out. recover_start accepts
{selection: {folders, ids, exclude}}.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b274f0b7ef
commit
ca677a8bc1
5 files changed
+410
-11
No files matched your search
@@ -470,6 +470,7 @@ impl Engine {
|
||||
scan_id: &str,
|
||||
ids: Option<Vec<u64>>,
|
||||
filter: Option<Query>,
|
||||
selection: Option<crate::explorer::Selection>,
|
||||
dest: &str,
|
||||
layout: recover::RecoverLayout,
|
||||
) -> Result<String> {
|
||||
@@ -477,15 +478,25 @@ impl Engine {
|
||||
let src = sj.source().ok_or_else(no_source)?;
|
||||
let files: Vec<Found> = {
|
||||
let s = sj.st.lock().unwrap();
|
||||
match (&ids, &filter) {
|
||||
(Some(ids), _) => ids
|
||||
.iter()
|
||||
.filter_map(|i| s.index.get(i).map(|&k| s.found[k].clone()))
|
||||
.collect(),
|
||||
(None, Some(q)) => q.select(&s.found).into_iter().cloned().collect(),
|
||||
(None, None) => s.found.clone(),
|
||||
if let Some(sel) = &selection {
|
||||
crate::explorer::resolve_selection(&s.found, sel)
|
||||
.into_iter()
|
||||
.cloned()
|
||||
.collect()
|
||||
} else {
|
||||
match (&ids, &filter) {
|
||||
(Some(ids), _) => ids
|
||||
.iter()
|
||||
.filter_map(|i| s.index.get(i).map(|&k| s.found[k].clone()))
|
||||
.collect(),
|
||||
(None, Some(q)) => q.select(&s.found).into_iter().cloned().collect(),
|
||||
(None, None) => s.found.clone(),
|
||||
}
|
||||
}
|
||||
};
|
||||
let roots = selection
|
||||
.as_ref()
|
||||
.map(|sel| recover::SelectionRoots::new(&sel.folders));
|
||||
if files.is_empty() {
|
||||
return Err(Error::msg("nenhum arquivo selecionado"));
|
||||
}
|
||||
@@ -533,11 +544,12 @@ impl Engine {
|
||||
};
|
||||
};
|
||||
let refs: Vec<&Found> = files.iter().collect();
|
||||
let res = recover::recover_resumable(
|
||||
let res = recover::recover_resumable_with(
|
||||
src.as_ref(),
|
||||
&refs,
|
||||
&dest_path,
|
||||
layout,
|
||||
roots.as_ref(),
|
||||
&source_key,
|
||||
true,
|
||||
&cancelled,
|
||||
@@ -1283,7 +1295,13 @@ impl Engine {
|
||||
.and_then(|v| v.as_str())
|
||||
.and_then(recover::RecoverLayout::parse)
|
||||
.unwrap_or_default();
|
||||
json!({ "job": self.start_recover(&s("job")?, ids, filter, &s("dest")?, layout)? })
|
||||
let selection: Option<crate::explorer::Selection> = p
|
||||
.get("selection")
|
||||
.cloned()
|
||||
.filter(|v| !v.is_null())
|
||||
.map(serde_json::from_value)
|
||||
.transpose()?;
|
||||
json!({ "job": self.start_recover(&s("job")?, ids, filter, selection, &s("dest")?, layout)? })
|
||||
}
|
||||
"image_start" => {
|
||||
let format: image::ImageFormat = p
|
||||
|
||||
Reference in new issue
Block a user