1use anyhow::Result;
2use dkdc_lake::Lake;
3use std::fs;
4use std::path::Path;
5
6pub fn list_files(path: &str) -> Result<()> {
7 let lake = Lake::new()?;
8 let files = lake.list_files(path)?;
9
10 for file in files {
11 println!("{}", file);
12 }
13
14 Ok(())
15}
16
17pub fn add_file(file: &str, path: Option<&str>) -> Result<()> {
18 let file_path = Path::new(file);
19
20 if !file_path.exists() {
21 anyhow::bail!("File not found: '{}'", file);
22 }
23
24 if !file_path.is_file() {
25 anyhow::bail!("'{}' is not a file", file);
26 }
27
28 let filename = file_path
29 .file_name()
30 .and_then(|n| n.to_str())
31 .ok_or_else(|| anyhow::anyhow!("Invalid filename"))?;
32
33 let data = fs::read(file_path)?;
34 let lake = Lake::new()?;
35 let filepath = path.unwrap_or("./files");
36
37 lake.add_file(filepath, filename, &data)?;
38
39 println!("{}", filename);
41
42 Ok(())
43}
44
45pub fn open_file(name: &str, path: &str) -> Result<()> {
46 use tempfile::Builder;
47
48 let editor = std::env::var("EDITOR").unwrap_or_else(|_| "vim".to_string());
49 let lake = Lake::new()?;
50
51 let existing_content = lake.get_file(path, name)?;
53 let initial_content = existing_content
54 .as_ref()
55 .map(|f| f.filedata.as_slice())
56 .unwrap_or(b"");
57
58 let extension = Path::new(name)
60 .extension()
61 .and_then(|ext| ext.to_str())
62 .map(|ext| format!(".{}", ext))
63 .unwrap_or_default();
64
65 let mut temp_file = Builder::new()
67 .prefix("dkdc_")
68 .suffix(&extension)
69 .tempfile()?;
70
71 use std::io::Write;
72 temp_file.write_all(initial_content)?;
73
74 let temp_path = temp_file.path().to_owned();
76
77 let _temp_file = temp_file.persist(&temp_path)?;
79
80 let status = std::process::Command::new(&editor)
82 .arg(&temp_path)
83 .status()?;
84
85 if !status.success() {
86 anyhow::bail!("Editor exited with error");
87 }
88
89 let final_content = fs::read(&temp_path)?;
91
92 if existing_content.is_none() && !final_content.is_empty() {
94 lake.add_file(path, name, &final_content)?;
95 } else if existing_content.is_some() && final_content != initial_content {
96 lake.add_file(path, name, &final_content)?;
97 }
98
99 fs::remove_file(temp_path)?;
101
102 Ok(())
103}
104
105pub fn dump_files(output: &str) -> Result<()> {
106 let output_path = Path::new(output);
107 fs::create_dir_all(output_path)?;
108
109 let lake = Lake::new()?;
110 let files = lake.list_files("./files")?;
111
112 for filename in &files {
113 if let Some(file) = lake.get_file("./files", filename)? {
114 let file_path = output_path.join(filename);
115 fs::write(&file_path, &file.filedata)?;
116 println!("{}", file_path.display());
118 }
119 }
120
121 Ok(())
122}
123
124pub fn restore_files(directory: &str) -> Result<()> {
125 let restore_path = Path::new(directory);
126
127 if !restore_path.exists() {
128 anyhow::bail!("Directory not found: {}", directory);
129 }
130
131 if !restore_path.is_dir() {
132 anyhow::bail!("Not a directory: {}", directory);
133 }
134
135 let lake = Lake::new()?;
136
137 for entry in fs::read_dir(restore_path)? {
138 let entry = entry?;
139 let path = entry.path();
140
141 if path.is_file() {
142 if let Some(filename) = path.file_name().and_then(|n| n.to_str()) {
143 let data = fs::read(&path)?;
144 lake.add_file("./files", filename, &data)?;
145 println!("{}", filename);
147 }
148 }
149 }
150
151 Ok(())
152}