feat(db): add an "INCOMING" rescan mode
ci/woodpecker/push/woodpecker Pipeline failed
Details
ci/woodpecker/push/woodpecker Pipeline failed
Details
parent
203b105b15
commit
d10b28621e
|
@ -42,6 +42,7 @@ use upend_db::stores::UpdateOptions;
|
||||||
use upend_db::stores::{Blob, UpStore};
|
use upend_db::stores::{Blob, UpStore};
|
||||||
use upend_db::UpEndDatabase;
|
use upend_db::UpEndDatabase;
|
||||||
use upend_db::VaultOptions;
|
use upend_db::VaultOptions;
|
||||||
|
use upend_db::VaultRescanMode;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[cfg(feature = "desktop")]
|
#[cfg(feature = "desktop")]
|
||||||
|
@ -767,6 +768,7 @@ pub async fn list_hier_roots(state: web::Data<State>) -> Result<HttpResponse, Er
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct RescanRequest {
|
pub struct RescanRequest {
|
||||||
initial: Option<bool>,
|
initial: Option<bool>,
|
||||||
|
tree_mode: Option<VaultRescanMode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/api/refresh")]
|
#[post("/api/refresh")]
|
||||||
|
@ -785,10 +787,12 @@ pub async fn api_refresh(
|
||||||
state.job_container.clone(),
|
state.job_container.clone(),
|
||||||
UpdateOptions {
|
UpdateOptions {
|
||||||
initial: query.initial.unwrap_or(false),
|
initial: query.initial.unwrap_or(false),
|
||||||
tree_mode: connection
|
tree_mode: query.tree_mode.unwrap_or(
|
||||||
.get_vault_options()?
|
connection
|
||||||
.tree_mode
|
.get_vault_options()?
|
||||||
.unwrap_or_default(),
|
.tree_mode
|
||||||
|
.unwrap_or_default(),
|
||||||
|
),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let _ = crate::extractors::extract_all(
|
let _ = crate::extractors::extract_all(
|
||||||
|
@ -1152,7 +1156,7 @@ mod tests {
|
||||||
job_container.clone(),
|
job_container.clone(),
|
||||||
UpdateOptions {
|
UpdateOptions {
|
||||||
initial: true,
|
initial: true,
|
||||||
tree_mode: upend_db::VaultTreeMode::default(),
|
tree_mode: upend_db::VaultRescanMode::default(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -241,9 +241,11 @@ impl UpEndConnection {
|
||||||
pub fn set_vault_options(&self, options: VaultOptions) -> Result<()> {
|
pub fn set_vault_options(&self, options: VaultOptions) -> Result<()> {
|
||||||
if let Some(tree_mode) = options.tree_mode {
|
if let Some(tree_mode) = options.tree_mode {
|
||||||
let tree_mode = match tree_mode {
|
let tree_mode = match tree_mode {
|
||||||
VaultTreeMode::Flat => "FLAT",
|
VaultRescanMode::Flat => "FLAT".to_string(),
|
||||||
VaultTreeMode::DepthFirst => "DEPTH_FIRST",
|
VaultRescanMode::DepthFirst => "DEPTH_FIRST".to_string(),
|
||||||
VaultTreeMode::Mirror => "MIRROR",
|
VaultRescanMode::Mirror => "MIRROR".to_string(),
|
||||||
|
VaultRescanMode::Incoming(None) => "INCOMING".to_string(),
|
||||||
|
VaultRescanMode::Incoming(Some(group)) => format!("INCOMING:{}", group),
|
||||||
};
|
};
|
||||||
self.set_meta("VAULT_TREE_MODE", tree_mode)?;
|
self.set_meta("VAULT_TREE_MODE", tree_mode)?;
|
||||||
}
|
}
|
||||||
|
@ -253,9 +255,13 @@ impl UpEndConnection {
|
||||||
pub fn get_vault_options(&self) -> Result<VaultOptions> {
|
pub fn get_vault_options(&self) -> Result<VaultOptions> {
|
||||||
let tree_mode = match self.get_meta("VAULT_TREE_MODE")? {
|
let tree_mode = match self.get_meta("VAULT_TREE_MODE")? {
|
||||||
Some(mode) => match mode.as_str() {
|
Some(mode) => match mode.as_str() {
|
||||||
"FLAT" => Some(VaultTreeMode::Flat),
|
"FLAT" => Some(VaultRescanMode::Flat),
|
||||||
"DEPTH_FIRST" => Some(VaultTreeMode::DepthFirst),
|
"DEPTH_FIRST" => Some(VaultRescanMode::DepthFirst),
|
||||||
"MIRROR" => Some(VaultTreeMode::Mirror),
|
"MIRROR" => Some(VaultRescanMode::Mirror),
|
||||||
|
"INCOMING" => Some(VaultRescanMode::Incoming(None)),
|
||||||
|
mode if mode.starts_with("INCOMING:") => {
|
||||||
|
Some(VaultRescanMode::Incoming(Some(mode[9..].to_string())))
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
warn!("Unknown vault tree mode: {}", mode);
|
warn!("Unknown vault tree mode: {}", mode);
|
||||||
None
|
None
|
||||||
|
@ -597,13 +603,18 @@ mod test {
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct VaultOptions {
|
pub struct VaultOptions {
|
||||||
pub tree_mode: Option<VaultTreeMode>,
|
pub tree_mode: Option<VaultRescanMode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
pub enum VaultTreeMode {
|
pub enum VaultRescanMode {
|
||||||
Flat,
|
|
||||||
DepthFirst,
|
|
||||||
#[default]
|
#[default]
|
||||||
|
/// Mirror the filesystem tree
|
||||||
Mirror,
|
Mirror,
|
||||||
|
/// Like Mirror, but chooses the shortest path
|
||||||
|
DepthFirst,
|
||||||
|
/// Use only the last level of the filesystem tree as groups
|
||||||
|
Flat,
|
||||||
|
/// Place all files in a single group
|
||||||
|
Incoming(Option<String>),
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@ use crate::hierarchies::{resolve_path, resolve_path_cached, ResolveCache, UHierP
|
||||||
use crate::jobs::{JobContainer, JobHandle};
|
use crate::jobs::{JobContainer, JobHandle};
|
||||||
use crate::util::hash_at_path;
|
use crate::util::hash_at_path;
|
||||||
use crate::{
|
use crate::{
|
||||||
ConnectionOptions, LoggingHandler, UpEndConnection, UpEndDatabase, VaultTreeMode, UPEND_SUBDIR,
|
ConnectionOptions, LoggingHandler, UpEndConnection, UpEndDatabase, VaultRescanMode,
|
||||||
|
UPEND_SUBDIR,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Error, Result};
|
use anyhow::{anyhow, Error, Result};
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
|
@ -134,7 +135,7 @@ impl FsStore {
|
||||||
|
|
||||||
let mut upaths: HashMap<PathBuf, UHierPath> = HashMap::new();
|
let mut upaths: HashMap<PathBuf, UHierPath> = HashMap::new();
|
||||||
match options.tree_mode {
|
match options.tree_mode {
|
||||||
VaultTreeMode::Flat => {
|
VaultRescanMode::Flat => {
|
||||||
for pb in &pathbufs {
|
for pb in &pathbufs {
|
||||||
let normalized_path = self.normalize_path(pb).unwrap();
|
let normalized_path = self.normalize_path(pb).unwrap();
|
||||||
let dirname = normalized_path.parent().and_then(|p| p.components().last());
|
let dirname = normalized_path.parent().and_then(|p| p.components().last());
|
||||||
|
@ -151,7 +152,7 @@ impl FsStore {
|
||||||
upaths.insert(pb.clone(), upath);
|
upaths.insert(pb.clone(), upath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VaultTreeMode::DepthFirst => {
|
VaultRescanMode::DepthFirst => {
|
||||||
let mut shallowest: HashMap<String, PathBuf> = HashMap::new();
|
let mut shallowest: HashMap<String, PathBuf> = HashMap::new();
|
||||||
for path in &pathbufs {
|
for path in &pathbufs {
|
||||||
let normalized_path = self.normalize_path(path).unwrap();
|
let normalized_path = self.normalize_path(path).unwrap();
|
||||||
|
@ -184,7 +185,7 @@ impl FsStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VaultTreeMode::Mirror => {
|
VaultRescanMode::Mirror => {
|
||||||
for pb in &pathbufs {
|
for pb in &pathbufs {
|
||||||
let normalized_path = self.normalize_path(&pb).unwrap();
|
let normalized_path = self.normalize_path(&pb).unwrap();
|
||||||
let path = normalized_path.parent().unwrap();
|
let path = normalized_path.parent().unwrap();
|
||||||
|
@ -198,6 +199,15 @@ impl FsStore {
|
||||||
upaths.insert(pb.clone(), UHierPath(upath));
|
upaths.insert(pb.clone(), UHierPath(upath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
VaultRescanMode::Incoming(group) => {
|
||||||
|
let upath = UHierPath(vec![group
|
||||||
|
.unwrap_or("INCOMING".to_string())
|
||||||
|
.parse()
|
||||||
|
.unwrap()]);
|
||||||
|
for pb in &pathbufs {
|
||||||
|
upaths.insert(pb.clone(), upath.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let path_entries = pathbufs
|
let path_entries = pathbufs
|
||||||
|
@ -860,7 +870,7 @@ mod test {
|
||||||
job_container,
|
job_container,
|
||||||
UpdateOptions {
|
UpdateOptions {
|
||||||
initial: true,
|
initial: true,
|
||||||
tree_mode: VaultTreeMode::default(),
|
tree_mode: VaultRescanMode::default(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
assert!(rescan_result.is_ok());
|
assert!(rescan_result.is_ok());
|
||||||
|
@ -906,7 +916,7 @@ mod test {
|
||||||
job,
|
job,
|
||||||
UpdateOptions {
|
UpdateOptions {
|
||||||
initial: quick,
|
initial: quick,
|
||||||
tree_mode: VaultTreeMode::default(),
|
tree_mode: VaultRescanMode::default(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -926,7 +936,7 @@ mod test {
|
||||||
job,
|
job,
|
||||||
UpdateOptions {
|
UpdateOptions {
|
||||||
initial: quick,
|
initial: quick,
|
||||||
tree_mode: VaultTreeMode::default(),
|
tree_mode: VaultRescanMode::default(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -949,7 +959,7 @@ mod test {
|
||||||
job,
|
job,
|
||||||
UpdateOptions {
|
UpdateOptions {
|
||||||
initial: quick,
|
initial: quick,
|
||||||
tree_mode: VaultTreeMode::default(),
|
tree_mode: VaultRescanMode::default(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -994,7 +1004,7 @@ mod test {
|
||||||
/// │ └── bar.txt
|
/// │ └── bar.txt
|
||||||
/// └── in_root.txt
|
/// └── in_root.txt
|
||||||
/// ```
|
/// ```
|
||||||
fn _prepare_hier_vault(tree_mode: VaultTreeMode) -> (UpEndConnection, TempDir) {
|
fn _prepare_hier_vault(tree_mode: VaultRescanMode) -> (UpEndConnection, TempDir) {
|
||||||
// Prepare temporary filesystem structure
|
// Prepare temporary filesystem structure
|
||||||
let temp_dir = TempDir::new().unwrap();
|
let temp_dir = TempDir::new().unwrap();
|
||||||
let temp_dir_path = temp_dir.path().canonicalize().unwrap();
|
let temp_dir_path = temp_dir.path().canonicalize().unwrap();
|
||||||
|
@ -1058,7 +1068,7 @@ mod test {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_initial_scan(mode: VaultTreeMode, expected_paths: Vec<&str>) {
|
fn test_initial_scan(mode: VaultRescanMode, expected_paths: Vec<&str>) {
|
||||||
let (connection, _vault_dir) = _prepare_hier_vault(mode);
|
let (connection, _vault_dir) = _prepare_hier_vault(mode);
|
||||||
assert_paths(expected_paths, &connection);
|
assert_paths(expected_paths, &connection);
|
||||||
}
|
}
|
||||||
|
@ -1066,7 +1076,7 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mirror_mode() {
|
fn test_mirror_mode() {
|
||||||
test_initial_scan(
|
test_initial_scan(
|
||||||
VaultTreeMode::Mirror,
|
VaultRescanMode::Mirror,
|
||||||
vec![
|
vec![
|
||||||
"NATIVE",
|
"NATIVE",
|
||||||
"NATIVE/nested_directory/nested_two/nested_three/foo.txt",
|
"NATIVE/nested_directory/nested_two/nested_three/foo.txt",
|
||||||
|
@ -1080,7 +1090,7 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_flat_mode() {
|
fn test_flat_mode() {
|
||||||
test_initial_scan(
|
test_initial_scan(
|
||||||
VaultTreeMode::Flat,
|
VaultRescanMode::Flat,
|
||||||
vec![
|
vec![
|
||||||
"NATIVE",
|
"NATIVE",
|
||||||
"NATIVE/nested_three/foo.txt",
|
"NATIVE/nested_three/foo.txt",
|
||||||
|
@ -1094,7 +1104,7 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_depth_mode() {
|
fn test_depth_mode() {
|
||||||
test_initial_scan(
|
test_initial_scan(
|
||||||
VaultTreeMode::DepthFirst,
|
VaultRescanMode::DepthFirst,
|
||||||
vec![
|
vec![
|
||||||
"NATIVE",
|
"NATIVE",
|
||||||
"NATIVE/nested_directory/nested_two/nested_four/baz.txt",
|
"NATIVE/nested_directory/nested_two/nested_four/baz.txt",
|
||||||
|
@ -1104,4 +1114,27 @@ mod test {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_incoming_mode() {
|
||||||
|
test_initial_scan(
|
||||||
|
VaultRescanMode::Incoming(None),
|
||||||
|
vec![
|
||||||
|
"INCOMING/foo.txt",
|
||||||
|
"INCOMING/baz.txt",
|
||||||
|
"INCOMING/bar.txt",
|
||||||
|
"INCOMING/in_root.txt",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
test_initial_scan(
|
||||||
|
VaultRescanMode::Incoming(Some("new files".to_string())),
|
||||||
|
vec![
|
||||||
|
"new files/foo.txt",
|
||||||
|
"new files/baz.txt",
|
||||||
|
"new files/bar.txt",
|
||||||
|
"new files/in_root.txt",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use super::{UpEndConnection, UpEndDatabase};
|
use super::{UpEndConnection, UpEndDatabase};
|
||||||
use crate::{jobs::JobContainer, VaultTreeMode};
|
use crate::{jobs::JobContainer, VaultRescanMode};
|
||||||
use upend_base::hash::UpMultihash;
|
use upend_base::hash::UpMultihash;
|
||||||
|
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
|
@ -73,5 +73,5 @@ pub trait UpStore {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct UpdateOptions {
|
pub struct UpdateOptions {
|
||||||
pub initial: bool,
|
pub initial: bool,
|
||||||
pub tree_mode: VaultTreeMode,
|
pub tree_mode: VaultRescanMode,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue