ipfrs_cli/commands/
dag.rs1use anyhow::Result;
11
12use crate::output::{error, format_bytes, print_cid, print_header, print_kv, success};
13use crate::progress;
14
15pub async fn dag_get(cid_str: &str, format: &str) -> Result<()> {
17 use ipfrs::{Node, NodeConfig};
18 use ipfrs_core::Cid;
19
20 let cid = cid_str
21 .parse::<Cid>()
22 .map_err(|e| anyhow::anyhow!("Invalid CID: {}", e))?;
23
24 let pb = progress::spinner(&format!("Retrieving DAG node {}", cid));
25 let mut node = Node::new(NodeConfig::default())?;
26 node.start().await?;
27
28 match node.dag_get(&cid).await? {
29 Some(ipld) => {
30 progress::finish_spinner_success(&pb, "DAG node retrieved");
31
32 match format {
33 "json" => {
34 let json = serde_json::to_string_pretty(&ipld)?;
36 println!("{}", json);
37 }
38 _ => {
39 print_header(&format!("DAG Node: {}", cid));
41 let json = serde_json::to_string_pretty(&ipld)?;
42 println!("{}", json);
43 }
44 }
45 }
46 None => {
47 progress::finish_spinner_error(&pb, "DAG node not found");
48 error(&format!("DAG node not found: {}", cid));
49 std::process::exit(1);
50 }
51 }
52
53 node.stop().await?;
54 Ok(())
55}
56
57pub async fn dag_put(data: &str, format: &str) -> Result<()> {
59 use ipfrs::{Node, NodeConfig};
60
61 let pb = progress::spinner("Parsing JSON data");
62
63 let ipld: ipfrs_core::Ipld =
65 serde_json::from_str(data).map_err(|e| anyhow::anyhow!("Invalid JSON: {}", e))?;
66
67 progress::finish_spinner_success(&pb, "JSON parsed");
68
69 let pb = progress::spinner("Storing DAG node");
70 let mut node = Node::new(NodeConfig::default())?;
71 node.start().await?;
72
73 let cid = node.dag_put(ipld).await?;
74 progress::finish_spinner_success(&pb, "DAG node stored");
75
76 match format {
77 "json" => {
78 println!("{{");
79 println!(" \"cid\": \"{}\"", cid);
80 println!("}}");
81 }
82 _ => {
83 success("DAG node stored");
84 print_cid("CID", &cid.to_string());
85 }
86 }
87
88 node.stop().await?;
89 Ok(())
90}
91
92pub async fn dag_resolve(path_str: &str, format: &str) -> Result<()> {
94 use ipfrs::{Node, NodeConfig};
95 use ipfrs_core::Cid;
96
97 let parts: Vec<&str> = path_str.trim_start_matches("/ipfs/").split('/').collect();
99
100 if parts.is_empty() {
101 return Err(anyhow::anyhow!("Invalid path: {}", path_str));
102 }
103
104 let root_cid_str = parts[0];
105 let sub_path = if parts.len() > 1 {
106 parts[1..].join("/")
107 } else {
108 String::new()
109 };
110
111 let root_cid = root_cid_str
112 .parse::<Cid>()
113 .map_err(|e| anyhow::anyhow!("Invalid CID: {}", e))?;
114
115 let pb = progress::spinner(&format!("Resolving path: {}", path_str));
116 let mut node = Node::new(NodeConfig::default())?;
117 node.start().await?;
118
119 match node.dag_resolve(&root_cid, &sub_path).await? {
120 Some(resolved_cid) => {
121 progress::finish_spinner_success(&pb, "Path resolved");
122
123 match format {
124 "json" => {
125 println!("{{");
126 println!(" \"cid\": \"{}\"", resolved_cid);
127 println!("}}");
128 }
129 _ => {
130 success(&format!("Resolved: {}", path_str));
131 print_cid("CID", &resolved_cid.to_string());
132 }
133 }
134 }
135 None => {
136 progress::finish_spinner_error(&pb, "Path not found");
137 error(&format!("Could not resolve path: {}", path_str));
138 std::process::exit(1);
139 }
140 }
141
142 node.stop().await?;
143 Ok(())
144}
145
146pub async fn dag_export(cid_str: &str, output_path: &str, format: &str) -> Result<()> {
148 use ipfrs::{Node, NodeConfig};
149 use ipfrs_core::Cid;
150
151 let cid = cid_str
152 .parse::<Cid>()
153 .map_err(|e| anyhow::anyhow!("Invalid CID: {}", e))?;
154
155 let pb = progress::spinner(&format!("Exporting DAG {} to {}", cid, output_path));
156 let mut node = Node::new(NodeConfig::default())?;
157 node.start().await?;
158
159 let stats = node.dag_export(&cid, output_path).await?;
160 progress::finish_spinner_success(&pb, "DAG exported successfully");
161
162 match format {
163 "json" => {
164 println!("{{");
165 println!(" \"blocks_exported\": {},", stats.blocks_exported);
166 println!(" \"bytes_exported\": {}", stats.bytes_exported);
167 println!("}}");
168 }
169 _ => {
170 success(&format!("Exported DAG to {}", output_path));
171 print_header("Export Statistics");
172 print_kv("Blocks exported", &stats.blocks_exported.to_string());
173 print_kv("Bytes exported", &format_bytes(stats.bytes_exported));
174 print_kv("File", output_path);
175 }
176 }
177
178 node.stop().await?;
179 Ok(())
180}
181
182pub async fn dag_import(car_path: &str, format: &str) -> Result<()> {
184 use ipfrs::{Node, NodeConfig};
185
186 let pb = progress::spinner(&format!("Importing DAG from {}", car_path));
187 let mut node = Node::new(NodeConfig::default())?;
188 node.start().await?;
189
190 let stats = node.dag_import(car_path).await?;
191 progress::finish_spinner_success(&pb, "DAG imported successfully");
192
193 match format {
194 "json" => {
195 println!("{{");
196 println!(" \"blocks_imported\": {},", stats.blocks_imported);
197 println!(" \"bytes_imported\": {}", stats.bytes_imported);
198 println!("}}");
199 }
200 _ => {
201 success(&format!("Imported DAG from {}", car_path));
202 print_header("Import Statistics");
203 print_kv("Blocks imported", &stats.blocks_imported.to_string());
204 print_kv("Bytes imported", &format_bytes(stats.bytes_imported));
205 }
206 }
207
208 node.stop().await?;
209 Ok(())
210}