420 lines
18 KiB
Rust
420 lines
18 KiB
Rust
use clap::{App, Arg, SubCommand};
|
|
use doctree::{DocTree, RedisStorage, Result, from_directory};
|
|
use std::path::Path;
|
|
|
|
fn main() -> Result<()> {
|
|
let matches = App::new("doctree")
|
|
.version("0.1.0")
|
|
.author("Your Name")
|
|
.about("A tool to manage document collections")
|
|
.arg(
|
|
Arg::with_name("debug")
|
|
.long("debug")
|
|
.help("Enable debug logging")
|
|
.takes_value(false)
|
|
)
|
|
.subcommand(
|
|
SubCommand::with_name("scan")
|
|
.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("doctree").long("doctree").takes_value(true).help("Name of the doctree (default: 'default')")),
|
|
)
|
|
.subcommand(
|
|
SubCommand::with_name("list")
|
|
.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("doctree").long("doctree").takes_value(true).help("Name of the doctree (default: 'default')")),
|
|
)
|
|
.subcommand(
|
|
SubCommand::with_name("get")
|
|
.about("Get page content")
|
|
.arg(Arg::with_name("collection")
|
|
.short("c".chars().next().unwrap())
|
|
.long("collection")
|
|
.takes_value(true)
|
|
.help("Name of the collection (optional)"))
|
|
.arg(Arg::with_name("page")
|
|
.short("p".chars().next().unwrap())
|
|
.long("page")
|
|
.required(true)
|
|
.takes_value(true)
|
|
.help("Name of the page"))
|
|
.arg(Arg::with_name("format")
|
|
.short("f".chars().next().unwrap())
|
|
.long("format")
|
|
.takes_value(true)
|
|
.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("doctree").long("doctree").takes_value(true).help("Name of the doctree (default: 'default')")),
|
|
)
|
|
.subcommand(
|
|
SubCommand::with_name("delete")
|
|
.about("Delete a collection from Redis")
|
|
.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")
|
|
.arg(Arg::with_name("doctree").long("doctree").takes_value(true).help("Name of the doctree (default: 'default')")),
|
|
)
|
|
.subcommand(
|
|
SubCommand::with_name("export_to_ipfs")
|
|
.about("Export a collection to IPFS")
|
|
.arg(Arg::with_name("collection").required(true).help("Name of the collection"))
|
|
.arg(Arg::with_name("output").required(true).help("Output directory for IPFS export"))
|
|
.arg(Arg::with_name("doctree").long("doctree").takes_value(true).help("Name of the doctree (default: 'default')")),
|
|
)
|
|
.get_matches();
|
|
|
|
// Check if debug mode is enabled
|
|
let debug_mode = matches.is_present("debug");
|
|
|
|
// Handle subcommands
|
|
if let Some(matches) = matches.subcommand_matches("scan") {
|
|
let path = matches.value_of("path").unwrap();
|
|
|
|
if debug_mode {
|
|
println!("DEBUG: Scanning path: {}", path);
|
|
}
|
|
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), Some(doctree_name))?;
|
|
|
|
// Print the discovered collections
|
|
let collections = doctree.list_collections();
|
|
if collections.is_empty() {
|
|
println!("No collections found");
|
|
} else {
|
|
println!("Discovered collections:");
|
|
for collection in collections {
|
|
println!("- {}", collection);
|
|
}
|
|
}
|
|
} else if let Some(matches) = matches.subcommand_matches("list") {
|
|
let doctree_name = matches.value_of("doctree").unwrap_or("default");
|
|
|
|
if debug_mode {
|
|
println!("DEBUG: Listing collections for doctree: {}", doctree_name);
|
|
}
|
|
|
|
// Create a storage with the specified doctree name
|
|
let storage = RedisStorage::new("redis://localhost:6379")?;
|
|
storage.set_doctree_name(doctree_name);
|
|
storage.set_debug(debug_mode);
|
|
|
|
if debug_mode {
|
|
println!("DEBUG: Connected to Redis storage");
|
|
}
|
|
|
|
// Get collections directly from Redis to avoid debug output from DocTree
|
|
let collections = storage.list_all_collections()?;
|
|
|
|
if collections.is_empty() {
|
|
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");
|
|
|
|
if debug_mode {
|
|
println!("DEBUG: Getting page '{}' from collection '{}' in doctree '{}' with format '{}'",
|
|
page, collection.unwrap_or("(default)"), doctree_name, format);
|
|
}
|
|
// Create a storage with the specified doctree name
|
|
let storage = RedisStorage::new("redis://localhost:6379")?;
|
|
storage.set_doctree_name(doctree_name);
|
|
storage.set_debug(debug_mode);
|
|
|
|
if debug_mode {
|
|
println!("DEBUG: Connected to Redis storage");
|
|
}
|
|
|
|
|
|
// 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");
|
|
|
|
if debug_mode {
|
|
println!("DEBUG: Getting HTML for page '{}' from collection '{}' in doctree '{}'",
|
|
page, collection, doctree_name);
|
|
}
|
|
// Create a storage with the specified doctree name
|
|
let storage = RedisStorage::new("redis://localhost:6379")?;
|
|
storage.set_doctree_name(doctree_name);
|
|
storage.set_debug(debug_mode);
|
|
|
|
if debug_mode {
|
|
println!("DEBUG: Connected to Redis storage");
|
|
}
|
|
|
|
|
|
// 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");
|
|
let collection_name = matches.value_of("collection");
|
|
|
|
if debug_mode {
|
|
if let Some(name) = collection_name {
|
|
println!("DEBUG: Getting info for collection '{}' in doctree '{}'", name, doctree_name);
|
|
} else {
|
|
println!("DEBUG: Getting info for all collections in doctree '{}'", doctree_name);
|
|
}
|
|
}
|
|
// Create a storage with the specified doctree name
|
|
let storage = RedisStorage::new("redis://localhost:6379")?;
|
|
storage.set_doctree_name(doctree_name);
|
|
storage.set_debug(debug_mode);
|
|
|
|
if debug_mode {
|
|
println!("DEBUG: Connected to Redis storage");
|
|
}
|
|
|
|
|
|
// 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
|
|
match doctree.get_collection(name) {
|
|
Ok(collection) => {
|
|
println!("Collection Information for '{}':", name);
|
|
println!(" Path: {:?}", collection.path);
|
|
println!(" Redis Key: {}:collections:{}", doctree_name, 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, doctree_name, 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<String> = 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, doctree_name, collection.name, image);
|
|
}
|
|
|
|
// Filter other files
|
|
let other_files: Vec<String> = 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, doctree_name, collection.name, file);
|
|
}
|
|
},
|
|
Err(e) => println!(" Error listing files: {}", e),
|
|
}
|
|
},
|
|
Err(e) => println!("Error: {}", e),
|
|
}
|
|
} else {
|
|
// Show info for all collections
|
|
let collections = doctree.list_collections();
|
|
if collections.is_empty() {
|
|
println!("No collections found");
|
|
} else {
|
|
println!("Collections in doctree '{}':", doctree_name);
|
|
for name in collections {
|
|
if let Ok(collection) = doctree.get_collection(&name) {
|
|
println!("- {} (Redis Key: {}:collections:{})", name, doctree_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("delete") {
|
|
let collection = matches.value_of("collection").unwrap();
|
|
let doctree_name = matches.value_of("doctree").unwrap_or("default");
|
|
|
|
if debug_mode {
|
|
println!("DEBUG: Deleting collection '{}' from doctree '{}'", collection, doctree_name);
|
|
}
|
|
// Create a storage with the specified doctree name
|
|
let storage = RedisStorage::new("redis://localhost:6379")?;
|
|
storage.set_doctree_name(doctree_name);
|
|
storage.set_debug(debug_mode);
|
|
if debug_mode {
|
|
println!("DEBUG: Connected to Redis storage");
|
|
}
|
|
|
|
|
|
// 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("export_to_ipfs") {
|
|
let collection_name = matches.value_of("collection").unwrap();
|
|
let output_path = matches.value_of("output").unwrap();
|
|
let doctree_name = matches.value_of("doctree").unwrap_or("default");
|
|
|
|
if debug_mode {
|
|
println!("DEBUG: Exporting collection '{}' from doctree '{}' to IPFS output path '{}'",
|
|
collection_name, doctree_name, output_path);
|
|
}
|
|
|
|
// Create a storage with the specified doctree name
|
|
let storage = RedisStorage::new("redis://localhost:6379")?;
|
|
storage.set_doctree_name(doctree_name);
|
|
storage.set_debug(debug_mode);
|
|
|
|
if debug_mode {
|
|
println!("DEBUG: Connected to Redis storage");
|
|
}
|
|
|
|
// 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()?;
|
|
|
|
// Get the collection
|
|
let collection = doctree.get_collection(collection_name)?;
|
|
|
|
// Call the synchronous export_collection_to_ipfs_sync function from the doctree crate
|
|
let output_path = Path::new(output_path);
|
|
doctree.export_collection_to_ipfs(collection_name, output_path)?;
|
|
|
|
println!("Successfully exported collection '{}' to IPFS and generated metadata CSV at {:?}.", collection_name, output_path.join(format!("{}.csv", collection_name)));
|
|
|
|
} else if let Some(matches) = matches.subcommand_matches("reset") {
|
|
let doctree_name = matches.value_of("doctree").unwrap_or("default");
|
|
|
|
if debug_mode {
|
|
println!("DEBUG: Resetting all collections in doctree '{}'", doctree_name);
|
|
}
|
|
|
|
// Create a storage with the specified doctree name
|
|
let storage = RedisStorage::new("redis://localhost:6379")?;
|
|
storage.set_doctree_name(doctree_name);
|
|
storage.set_debug(debug_mode);
|
|
|
|
if debug_mode {
|
|
println!("DEBUG: Connected to Redis storage");
|
|
}
|
|
|
|
// 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.");
|
|
}
|
|
|
|
Ok(())
|
|
}
|