diff --git a/doctree/src/doctree.rs b/doctree/src/doctree.rs index 910f160..167fe2c 100644 --- a/doctree/src/doctree.rs +++ b/doctree/src/doctree.rs @@ -38,6 +38,9 @@ pub struct DocTree { /// Redis storage backend storage: RedisStorage, + /// Name of the doctree (used as prefix for Redis keys) + pub doctree_name: String, + /// For backward compatibility pub name: String, @@ -56,6 +59,9 @@ pub struct DocTreeBuilder { /// Redis storage backend storage: Option, + /// Name of the doctree (used as prefix for Redis keys) + doctree_name: Option, + /// For backward compatibility name: Option, @@ -74,6 +80,7 @@ impl DocTree { collections: HashMap::new(), default_collection: None, storage: None, + doctree_name: Some("default".to_string()), name: None, path: None, } @@ -92,8 +99,12 @@ impl DocTree { pub fn add_collection>(&mut self, path: P, name: &str) -> Result<&Collection> { // Create a new collection let namefixed = name_fix(name); + // Clone the storage and set the doctree name + let mut storage = self.storage.clone(); + storage.set_doctree_name(&self.doctree_name); + let collection = Collection::builder(path, &namefixed) - .with_storage(self.storage.clone()) + .with_storage(storage) .build()?; // Scan the collection @@ -531,6 +542,20 @@ impl DocTreeBuilder { /// # Returns /// /// Self for method chaining + /// Set the doctree name + /// + /// # Arguments + /// + /// * `name` - Name of the doctree + /// + /// # Returns + /// + /// Self for method chaining + pub fn with_doctree_name(mut self, name: &str) -> Self { + self.doctree_name = Some(name.to_string()); + self + } + pub fn with_storage(mut self, storage: RedisStorage) -> Self { self.storage = Some(storage); self @@ -552,10 +577,18 @@ impl DocTreeBuilder { DocTreeError::MissingParameter("storage".to_string()) })?; + // Get the doctree name + let doctree_name = self.doctree_name.clone().unwrap_or_else(|| "default".to_string()); + // Create a new collection let namefixed = name_fix(name); + + // Clone the storage and set the doctree name + let mut storage_clone = storage.clone(); + storage_clone.set_doctree_name(&doctree_name); + let collection = Collection::builder(path.as_ref(), &namefixed) - .with_storage(storage.clone()) + .with_storage(storage_clone) .build()?; // Scan the collection @@ -604,11 +637,19 @@ impl DocTreeBuilder { DocTreeError::MissingParameter("storage".to_string()) })?; + // Get the doctree name + let doctree_name = self.doctree_name.clone().unwrap_or_else(|| "default".to_string()); + + // Clone the storage and set the doctree name + let mut storage_clone = storage.clone(); + storage_clone.set_doctree_name(&doctree_name); + // Create a temporary DocTree to scan collections let mut temp_doctree = DocTree { collections: HashMap::new(), default_collection: None, - storage: storage.clone(), + storage: storage_clone, + doctree_name: doctree_name, name: self.name.clone().unwrap_or_default(), path: self.path.clone().unwrap_or_else(|| PathBuf::from("")), }; @@ -641,11 +682,19 @@ impl DocTreeBuilder { DocTreeError::MissingParameter("storage".to_string()) })?; + // Get the doctree name + let doctree_name = self.doctree_name.unwrap_or_else(|| "default".to_string()); + + // Set the doctree name in the storage + let mut storage_clone = storage.clone(); + storage_clone.set_doctree_name(&doctree_name); + // Create the DocTree let mut doctree = DocTree { collections: self.collections, default_collection: self.default_collection, - storage: storage.clone(), + storage: storage_clone, + doctree_name, name: self.name.unwrap_or_default(), path: self.path.unwrap_or_else(|| PathBuf::from("")), }; @@ -684,6 +733,12 @@ pub fn new>(args: &[&str]) -> Result { let mut builder = DocTree::builder().with_storage(storage); + // If the first argument is a doctree name, use it + if args.len() >= 1 && args[0].starts_with("--doctree=") { + let doctree_name = args[0].trim_start_matches("--doctree="); + builder = builder.with_doctree_name(doctree_name); + } + // For backward compatibility with existing code if args.len() == 2 { let path = args[0]; @@ -707,15 +762,20 @@ pub fn new>(args: &[&str]) -> Result { /// # Arguments /// /// * `root_path` - The root path to scan for collections +/// * `doctree_name` - Optional name for the doctree (default: "default") /// /// # Returns /// /// A new DocTree or an error -pub fn from_directory>(root_path: P) -> Result { +pub fn from_directory>(root_path: P, doctree_name: Option<&str>) -> Result { let storage = RedisStorage::new("redis://localhost:6379")?; - DocTree::builder() - .with_storage(storage) - .scan_collections(root_path)? - .build() + let mut builder = DocTree::builder().with_storage(storage); + + // Set the doctree name if provided + if let Some(name) = doctree_name { + builder = builder.with_doctree_name(name); + } + + builder.scan_collections(root_path)?.build() } \ No newline at end of file diff --git a/doctree/src/storage.rs b/doctree/src/storage.rs index d8fa6cb..eaee263 100644 --- a/doctree/src/storage.rs +++ b/doctree/src/storage.rs @@ -8,6 +8,8 @@ pub struct RedisStorage { client: Client, // Connection pool connection: Arc>, + // Doctree name for key prefixing + doctree_name: Arc>, } impl RedisStorage { @@ -31,9 +33,30 @@ impl RedisStorage { Ok(Self { client, connection: Arc::new(Mutex::new(connection)), + doctree_name: Arc::new(Mutex::new("default".to_string())), }) } + /// Set the doctree name for key prefixing + /// + /// # Arguments + /// + /// * `name` - Doctree name + pub fn set_doctree_name(&self, name: &str) { + let mut doctree_name = self.doctree_name.lock().unwrap(); + *doctree_name = name.to_string(); + } + + /// Get the doctree name + /// + /// # Returns + /// + /// The doctree name + pub fn get_doctree_name(&self) -> String { + let doctree_name = self.doctree_name.lock().unwrap(); + doctree_name.clone() + } + /// Store a collection entry /// /// # Arguments @@ -46,7 +69,8 @@ impl RedisStorage { /// /// Ok(()) on success or an error pub fn store_collection_entry(&self, collection: &str, key: &str, value: &str) -> Result<()> { - let redis_key = format!("collections:{}", collection); + let doctree_name = self.get_doctree_name(); + let redis_key = format!("{}:collections:{}", doctree_name, collection); println!("DEBUG: Redis operation - HSET {} {} {}", redis_key, key, value); // Get a connection from the pool @@ -76,7 +100,8 @@ impl RedisStorage { /// /// The entry value or an error pub fn get_collection_entry(&self, collection: &str, key: &str) -> Result { - let collection_key = format!("collections:{}", collection); + let doctree_name = self.get_doctree_name(); + let collection_key = format!("{}:collections:{}", doctree_name, collection); println!("DEBUG: Redis operation - HGET {} {}", collection_key, key); // Get a connection from the pool @@ -115,7 +140,8 @@ impl RedisStorage { /// /// Ok(()) on success or an error pub fn delete_collection_entry(&self, collection: &str, key: &str) -> Result<()> { - let collection_key = format!("collections:{}", collection); + let doctree_name = self.get_doctree_name(); + let collection_key = format!("{}:collections:{}", doctree_name, collection); println!("DEBUG: Redis operation - HDEL {} {}", collection_key, key); // Get a connection from the pool @@ -153,7 +179,8 @@ impl RedisStorage { /// /// A vector of entry keys or an error pub fn list_collection_entries(&self, collection: &str) -> Result> { - let collection_key = format!("collections:{}", collection); + let doctree_name = self.get_doctree_name(); + let collection_key = format!("{}:collections:{}", doctree_name, collection); println!("DEBUG: Redis operation - HKEYS {}", collection_key); // Get a connection from the pool @@ -191,7 +218,8 @@ impl RedisStorage { /// /// Ok(()) on success or an error pub fn delete_collection(&self, collection: &str) -> Result<()> { - let redis_key = format!("collections:{}", collection); + let doctree_name = self.get_doctree_name(); + let redis_key = format!("{}:collections:{}", doctree_name, collection); println!("DEBUG: Redis operation - DEL {}", redis_key); // Get a connection from the pool @@ -217,7 +245,8 @@ impl RedisStorage { /// /// true if the collection exists, false otherwise pub fn collection_exists(&self, collection: &str) -> Result { - let collection_key = format!("collections:{}", collection); + let doctree_name = self.get_doctree_name(); + let collection_key = format!("{}:collections:{}", doctree_name, collection); println!("DEBUG: Redis operation - EXISTS {}", collection_key); // Get a connection from the pool @@ -241,22 +270,27 @@ impl RedisStorage { /// /// A vector of collection names or an error pub fn list_all_collections(&self) -> Result> { - println!("DEBUG: Redis operation - KEYS collections:*"); + let doctree_name = self.get_doctree_name(); + println!("DEBUG: Redis operation - KEYS {}:collections:*", doctree_name); // Get a connection from the pool let mut conn = self.connection.lock().unwrap(); // Get all collection keys + let pattern = format!("{}:collections:*", doctree_name); let keys: Vec = redis::cmd("KEYS") - .arg("collections:*") + .arg(&pattern) .query(&mut *conn) .map_err(|e| DocTreeError::RedisError(format!("Redis error: {}", e)))?; - // Extract collection names from keys (remove the "collections:" prefix) + // Extract collection names from keys (remove the "{doctree_name}:collections:" prefix) + let prefix = format!("{}:collections:", doctree_name); + let prefix_len = prefix.len(); + let collections = keys.iter() .filter_map(|key| { - if key.starts_with("collections:") { - Some(key[12..].to_string()) + if key.starts_with(&prefix) { + Some(key[prefix_len..].to_string()) } else { None } @@ -274,14 +308,16 @@ impl RedisStorage { /// /// Ok(()) on success or an error pub fn delete_all_collections(&self) -> Result<()> { - println!("DEBUG: Redis operation - KEYS collections:*"); + let doctree_name = self.get_doctree_name(); + println!("DEBUG: Redis operation - KEYS {}:collections:*", doctree_name); // Get a connection from the pool let mut conn = self.connection.lock().unwrap(); // Get all collection keys + let pattern = format!("{}:collections:*", doctree_name); let keys: Vec = redis::cmd("KEYS") - .arg("collections:*") + .arg(&pattern) .query(&mut *conn) .map_err(|e| DocTreeError::RedisError(format!("Redis error: {}", e)))?; @@ -298,6 +334,7 @@ impl RedisStorage { Ok(()) } + /// Store a collection's path /// /// # Arguments @@ -309,7 +346,8 @@ impl RedisStorage { /// /// Ok(()) on success or an error pub fn store_collection_path(&self, collection: &str, path: &str) -> Result<()> { - let redis_key = format!("collections:{}:path", collection); + let doctree_name = self.get_doctree_name(); + let redis_key = format!("{}:collections:{}:path", doctree_name, collection); println!("DEBUG: Redis operation - SET {} {}", redis_key, path); // Get a connection from the pool @@ -337,7 +375,8 @@ impl RedisStorage { /// /// The collection path or an error pub fn get_collection_path(&self, collection: &str) -> Result { - let redis_key = format!("collections:{}:path", collection); + let doctree_name = self.get_doctree_name(); + let redis_key = format!("{}:collections:{}:path", doctree_name, collection); println!("DEBUG: Redis operation - GET {}", redis_key); // Get a connection from the pool @@ -375,6 +414,7 @@ impl Clone for RedisStorage { Self { client: self.client.clone(), connection: Arc::new(Mutex::new(connection)), + doctree_name: self.doctree_name.clone(), } } } \ No newline at end of file diff --git a/doctreecmd/src/main.rs b/doctreecmd/src/main.rs index 178a464..4ee07f9 100644 --- a/doctreecmd/src/main.rs +++ b/doctreecmd/src/main.rs @@ -9,29 +9,20 @@ fn main() -> Result<()> { .about("A tool to manage document collections") .subcommand( SubCommand::with_name("scan") - .about("Scan a directory and create a collection") + .about("Scan a directory for .collection files and create collections") .arg(Arg::with_name("path").required(true).help("Path to the directory")) - .arg(Arg::with_name("name").required(true).help("Name of the collection")), + .arg(Arg::with_name("doctree").long("doctree").takes_value(true).help("Name of the doctree (default: 'default')")), ) .subcommand( SubCommand::with_name("list") - .about("List collections"), - ) - .subcommand( - SubCommand::with_name("scan-collections") - .about("Recursively scan directories for .collection files") - .arg(Arg::with_name("path").required(true).help("Root path to scan for collections")), - ) - .subcommand( - SubCommand::with_name("scan-and-info") - .about("Scan collections and show detailed information") - .arg(Arg::with_name("path").required(true).help("Root path to scan for collections")) - .arg(Arg::with_name("collection").help("Name of the collection (optional)")), + .about("List collections") + .arg(Arg::with_name("doctree").long("doctree").takes_value(true).help("Name of the doctree (default: 'default')")), ) .subcommand( SubCommand::with_name("info") .about("Show detailed information about collections") - .arg(Arg::with_name("collection").help("Name of the collection (optional)")), + .arg(Arg::with_name("collection").help("Name of the collection (optional)")) + .arg(Arg::with_name("doctree").long("doctree").takes_value(true).help("Name of the doctree (default: 'default')")), ) .subcommand( SubCommand::with_name("get") @@ -51,87 +42,39 @@ fn main() -> Result<()> { .short("f".chars().next().unwrap()) .long("format") .takes_value(true) - .help("Output format (html or markdown, default: markdown)")), + .help("Output format (html or markdown, default: markdown)")) + .arg(Arg::with_name("doctree").long("doctree").takes_value(true).help("Name of the doctree (default: 'default')")), ) .subcommand( SubCommand::with_name("html") .about("Get page content as HTML") .arg(Arg::with_name("collection").required(true).help("Name of the collection")) - .arg(Arg::with_name("page").required(true).help("Name of the page")), + .arg(Arg::with_name("page").required(true).help("Name of the page")) + .arg(Arg::with_name("doctree").long("doctree").takes_value(true).help("Name of the doctree (default: 'default')")), ) .subcommand( SubCommand::with_name("delete-collection") .about("Delete a collection from Redis") - .arg(Arg::with_name("collection").required(true).help("Name of the collection")), + .arg(Arg::with_name("collection").required(true).help("Name of the collection")) + .arg(Arg::with_name("doctree").long("doctree").takes_value(true).help("Name of the doctree (default: 'default')")), ) .subcommand( SubCommand::with_name("reset") - .about("Delete all collections from Redis"), + .about("Delete all collections from Redis") + .arg(Arg::with_name("doctree").long("doctree").takes_value(true).help("Name of the doctree (default: 'default')")), ) .get_matches(); - // Create a Redis storage instance - let storage = RedisStorage::new("redis://localhost:6379")?; - - // Create a DocTree instance - let mut doctree = DocTree::builder() - .with_storage(storage) - .build()?; - // Handle subcommands if let Some(matches) = matches.subcommand_matches("scan") { let path = matches.value_of("path").unwrap(); - let name = matches.value_of("name").unwrap(); - - println!("Scanning directory: {}", path); - doctree.add_collection(Path::new(path), name)?; - println!("Collection '{}' created successfully", name); - } else if let Some(_) = matches.subcommand_matches("list") { - let collections = doctree.list_collections(); - - if collections.is_empty() { - println!("No collections found"); - } else { - println!("Collections:"); - for collection in collections { - println!("- {}", collection); - } - } - } else if let Some(matches) = matches.subcommand_matches("get") { - let collection = matches.value_of("collection"); - let page = matches.value_of("page").unwrap(); - let format = matches.value_of("format").unwrap_or("markdown"); - - if format.to_lowercase() == "html" { - let html = doctree.page_get_html(collection, page)?; - println!("{}", html); - } else { - let content = doctree.page_get(collection, page)?; - println!("{}", content); - } - } else if let Some(matches) = matches.subcommand_matches("html") { - let collection = matches.value_of("collection").unwrap(); - let page = matches.value_of("page").unwrap(); - - let html = doctree.page_get_html(Some(collection), page)?; - println!("{}", html); - } else if let Some(matches) = matches.subcommand_matches("delete-collection") { - let collection = matches.value_of("collection").unwrap(); - - println!("Deleting collection '{}' from Redis...", collection); - doctree.delete_collection(collection)?; - println!("Collection '{}' deleted successfully", collection); - } else if let Some(_) = matches.subcommand_matches("reset") { - println!("Deleting all collections from Redis..."); - doctree.delete_all_collections()?; - println!("All collections deleted successfully"); - } else if let Some(matches) = matches.subcommand_matches("scan-collections") { - let path = matches.value_of("path").unwrap(); + let doctree_name = matches.value_of("doctree").unwrap_or("default"); println!("Recursively scanning for collections in: {}", path); + println!("Using doctree name: {}", doctree_name); // Use the from_directory function to create a DocTree with all collections - let doctree = from_directory(Path::new(path))?; + let doctree = from_directory(Path::new(path), Some(doctree_name))?; // Print the discovered collections let collections = doctree.list_collections(); @@ -143,28 +86,92 @@ fn main() -> Result<()> { println!("- {}", collection); } } - } else if let Some(matches) = matches.subcommand_matches("scan-and-info") { - let path = matches.value_of("path").unwrap(); - let collection_name = matches.value_of("collection"); + } else if let Some(matches) = matches.subcommand_matches("list") { + let doctree_name = matches.value_of("doctree").unwrap_or("default"); - println!("Recursively scanning for collections in: {}", path); + // Create a storage with the specified doctree name + let mut storage = RedisStorage::new("redis://localhost:6379")?; + storage.set_doctree_name(doctree_name); - // Use the from_directory function to create a DocTree with all collections - let doctree = from_directory(Path::new(path))?; + // Create a DocTree with the specified doctree name + let doctree = DocTree::builder() + .with_storage(storage) + .with_doctree_name(doctree_name) + .build()?; - // Print the discovered collections let collections = doctree.list_collections(); + if collections.is_empty() { - println!("No collections found"); - return Ok(()); + println!("No collections found in doctree '{}'", doctree_name); + } else { + println!("Collections in doctree '{}':", doctree_name); + for collection in collections { + println!("- {}", collection); + } } + } else if let Some(matches) = matches.subcommand_matches("get") { + let collection = matches.value_of("collection"); + let page = matches.value_of("page").unwrap(); + let format = matches.value_of("format").unwrap_or("markdown"); + let doctree_name = matches.value_of("doctree").unwrap_or("default"); - println!("Discovered collections:"); - for collection in &collections { - println!("- {}", collection); + // Create a storage with the specified doctree name + let mut storage = RedisStorage::new("redis://localhost:6379")?; + storage.set_doctree_name(doctree_name); + + // Create a DocTree with the specified doctree name + let mut doctree = DocTree::builder() + .with_storage(storage) + .with_doctree_name(doctree_name) + .build()?; + + // Load collections from Redis + doctree.load_collections_from_redis()?; + + if format.to_lowercase() == "html" { + let html = doctree.page_get_html(collection, page)?; + println!("{}", html); + } else { + let content = doctree.page_get(collection, page)?; + println!("{}", content); } + } else if let Some(matches) = matches.subcommand_matches("html") { + let collection = matches.value_of("collection").unwrap(); + let page = matches.value_of("page").unwrap(); + let doctree_name = matches.value_of("doctree").unwrap_or("default"); - println!("\nDetailed Collection Information:"); + // Create a storage with the specified doctree name + let mut storage = RedisStorage::new("redis://localhost:6379")?; + storage.set_doctree_name(doctree_name); + + // Create a DocTree with the specified doctree name + let mut doctree = DocTree::builder() + .with_storage(storage) + .with_doctree_name(doctree_name) + .build()?; + + // Load collections from Redis + doctree.load_collections_from_redis()?; + + let html = doctree.page_get_html(Some(collection), page)?; + println!("{}", html); + } else if let Some(matches) = matches.subcommand_matches("info") { + let doctree_name = matches.value_of("doctree").unwrap_or("default"); + + // Create a storage with the specified doctree name + let mut storage = RedisStorage::new("redis://localhost:6379")?; + storage.set_doctree_name(doctree_name); + + // Create a DocTree with the specified doctree name + let mut doctree = DocTree::builder() + .with_storage(storage) + .with_doctree_name(doctree_name) + .build()?; + + // Load collections from Redis + doctree.load_collections_from_redis()?; + + let collection_name = matches.value_of("collection"); if let Some(name) = collection_name { // Show info for a specific collection @@ -172,7 +179,7 @@ fn main() -> Result<()> { Ok(collection) => { println!("Collection Information for '{}':", name); println!(" Path: {:?}", collection.path); - println!(" Redis Key: collections:{}", collection.name); + println!(" Redis Key: {}:collections:{}", doctree_name, collection.name); // List documents match collection.page_list() { @@ -181,7 +188,7 @@ fn main() -> Result<()> { for page in pages { match collection.page_get_path(&page) { Ok(path) => { - println!(" - {} => Redis: collections:{} / {}", path, collection.name, page); + println!(" - {} => Redis: {}:collections:{} / {}", path, doctree_name, collection.name, page); }, Err(_) => { println!(" - {}", page); @@ -206,7 +213,7 @@ fn main() -> Result<()> { println!(" Images ({}):", images.len()); for image in images { - println!(" - {} => Redis: collections:{} / {}", image, collection.name, image); + println!(" - {} => Redis: {}:collections:{} / {}", image, doctree_name, collection.name, image); } // Filter other files @@ -220,97 +227,7 @@ fn main() -> Result<()> { println!(" Other Files ({}):", other_files.len()); for file in other_files { - println!(" - {} => Redis: collections:{} / {}", file, collection.name, file); - } - }, - Err(e) => println!(" Error listing files: {}", e), - } - }, - Err(e) => println!("Error: {}", e), - } - } else { - // Show info for all collections - for name in collections { - if let Ok(collection) = doctree.get_collection(&name) { - println!("- {} (Redis Key: collections:{})", name, collection.name); - println!(" Path: {:?}", collection.path); - - // Count documents and images - if let Ok(pages) = collection.page_list() { - println!(" Documents: {}", pages.len()); - } - - if let Ok(files) = collection.file_list() { - let image_count = files.iter() - .filter(|f| - f.ends_with(".png") || f.ends_with(".jpg") || - f.ends_with(".jpeg") || f.ends_with(".gif") || - f.ends_with(".svg")) - .count(); - println!(" Images: {}", image_count); - println!(" Other Files: {}", files.len() - image_count); - } - } - } - } - } else if let Some(matches) = matches.subcommand_matches("info") { - let collection_name = matches.value_of("collection"); - - if let Some(name) = collection_name { - // Show info for a specific collection - match doctree.get_collection(name) { - Ok(collection) => { - println!("Collection Information for '{}':", name); - println!(" Path: {:?}", collection.path); - println!(" Redis Key: collections:{}", collection.name); - - // List documents - match collection.page_list() { - Ok(pages) => { - println!(" Documents ({}):", pages.len()); - for page in pages { - match collection.page_get_path(&page) { - Ok(path) => { - println!(" - {} => Redis: collections:{} / {}", path, collection.name, page); - }, - Err(_) => { - println!(" - {}", page); - } - } - } - }, - Err(e) => println!(" Error listing documents: {}", e), - } - - // List files - match collection.file_list() { - Ok(files) => { - // Filter images - let images: Vec = files.iter() - .filter(|f| - f.ends_with(".png") || f.ends_with(".jpg") || - f.ends_with(".jpeg") || f.ends_with(".gif") || - f.ends_with(".svg")) - .cloned() - .collect(); - - println!(" Images ({}):", images.len()); - for image in images { - println!(" - {} => Redis: collections:{} / {}", image, collection.name, image); - } - - // Filter other files - let other_files: Vec = files.iter() - .filter(|f| - !f.ends_with(".png") && !f.ends_with(".jpg") && - !f.ends_with(".jpeg") && !f.ends_with(".gif") && - !f.ends_with(".svg")) - .cloned() - .collect(); - - println!(" Other Files ({}):", other_files.len()); - for file in other_files { - println!(" - {} => Redis: collections:{} / {}", file, collection.name, file); + println!(" - {} => Redis: {}:collections:{} / {}", file, doctree_name, collection.name, file); } }, Err(e) => println!(" Error listing files: {}", e), @@ -324,10 +241,10 @@ fn main() -> Result<()> { if collections.is_empty() { println!("No collections found"); } else { - println!("Collections:"); + println!("Collections in doctree '{}':", doctree_name); for name in collections { if let Ok(collection) = doctree.get_collection(&name) { - println!("- {} (Redis Key: collections:{})", name, collection.name); + println!("- {} (Redis Key: {}:collections:{})", name, doctree_name, collection.name); println!(" Path: {:?}", collection.path); // Count documents and images @@ -337,9 +254,9 @@ fn main() -> Result<()> { if let Ok(files) = collection.file_list() { let image_count = files.iter() - .filter(|f| - f.ends_with(".png") || f.ends_with(".jpg") || - f.ends_with(".jpeg") || f.ends_with(".gif") || + .filter(|f| + f.ends_with(".png") || f.ends_with(".jpg") || + f.ends_with(".jpeg") || f.ends_with(".gif") || f.ends_with(".svg")) .count(); println!(" Images: {}", image_count); @@ -349,6 +266,39 @@ fn main() -> Result<()> { } } } + } else if let Some(matches) = matches.subcommand_matches("delete-collection") { + let collection = matches.value_of("collection").unwrap(); + let doctree_name = matches.value_of("doctree").unwrap_or("default"); + + // Create a storage with the specified doctree name + let mut storage = RedisStorage::new("redis://localhost:6379")?; + storage.set_doctree_name(doctree_name); + + // Create a DocTree with the specified doctree name + let mut doctree = DocTree::builder() + .with_storage(storage) + .with_doctree_name(doctree_name) + .build()?; + + println!("Deleting collection '{}' from Redis in doctree '{}'...", collection, doctree_name); + doctree.delete_collection(collection)?; + println!("Collection '{}' deleted successfully", collection); + } else if let Some(matches) = matches.subcommand_matches("reset") { + let doctree_name = matches.value_of("doctree").unwrap_or("default"); + + // Create a storage with the specified doctree name + let mut storage = RedisStorage::new("redis://localhost:6379")?; + storage.set_doctree_name(doctree_name); + + // Create a DocTree with the specified doctree name + let mut doctree = DocTree::builder() + .with_storage(storage) + .with_doctree_name(doctree_name) + .build()?; + + println!("Deleting all collections from Redis in doctree '{}'...", doctree_name); + doctree.delete_all_collections()?; + println!("All collections deleted successfully"); } else { println!("No command specified. Use --help for usage information."); } diff --git a/example_commands.sh b/example_commands.sh index 49a69a6..5001782 100755 --- a/example_commands.sh +++ b/example_commands.sh @@ -7,7 +7,7 @@ set -e cd doctreecmd echo "=== Scanning Collections ===" -cargo run -- scan-collections ../examples +cargo run -- scan ../examples echo -e "\n=== Listing Collections ===" cargo run -- list