ipfrs_cli/commands/
pin.rs1use anyhow::Result;
10
11use crate::output::{self, error, print_header, print_kv, success};
12use crate::progress;
13
14pub async fn pin_add(cid_str: &str, recursive: bool, name: Option<&str>) -> Result<()> {
16 use ipfrs::{Node, NodeConfig};
17 use ipfrs_core::Cid;
18
19 let cid = cid_str
20 .parse::<Cid>()
21 .map_err(|e| anyhow::anyhow!("Invalid CID: {}", e))?;
22
23 let pb = progress::spinner(&format!("Pinning {}", cid));
24 let mut node = Node::new(NodeConfig::default())?;
25 node.start().await?;
26
27 node.pin_add(&cid, recursive, name.map(|s| s.to_string()))
28 .await?;
29 progress::finish_spinner_success(&pb, "Pinned successfully");
30
31 let pin_type = if recursive { "recursively" } else { "directly" };
32 success(&format!("Pinned {} {}", cid, pin_type));
33 if let Some(n) = name {
34 print_kv("Name", n);
35 }
36
37 node.stop().await?;
38 Ok(())
39}
40
41pub async fn pin_rm(cid_str: &str, recursive: bool) -> Result<()> {
43 use ipfrs::{Node, NodeConfig};
44 use ipfrs_core::Cid;
45
46 let cid = cid_str
47 .parse::<Cid>()
48 .map_err(|e| anyhow::anyhow!("Invalid CID: {}", e))?;
49
50 let pb = progress::spinner(&format!("Unpinning {}", cid));
51 let mut node = Node::new(NodeConfig::default())?;
52 node.start().await?;
53
54 node.pin_rm(&cid, recursive).await?;
55 progress::finish_spinner_success(&pb, "Unpinned successfully");
56
57 success(&format!("Unpinned {}", cid));
58
59 node.stop().await?;
60 Ok(())
61}
62
63pub async fn pin_ls(_pin_type: &str, format: &str) -> Result<()> {
65 use ipfrs::{Node, NodeConfig};
66
67 let pb = progress::spinner("Listing pins");
68 let mut node = Node::new(NodeConfig::default())?;
69 node.start().await?;
70
71 let pins = node.pin_ls()?;
72 progress::finish_spinner_success(&pb, "Pins listed");
73
74 match format {
75 "json" => {
76 println!("[");
77 for (i, pin_info) in pins.iter().enumerate() {
78 print!(
79 " {{\"cid\": \"{}\", \"type\": \"{:?}\"}}",
80 pin_info.cid, pin_info.pin_type
81 );
82 if i < pins.len() - 1 {
83 println!(",");
84 } else {
85 println!();
86 }
87 }
88 println!("]");
89 }
90 _ => {
91 if pins.is_empty() {
92 output::info("No pinned content");
93 } else {
94 print_header(&format!("Pinned Content ({})", pins.len()));
95 for pin_info in pins {
96 println!(" {} ({:?})", pin_info.cid, pin_info.pin_type);
97 }
98 }
99 }
100 }
101
102 node.stop().await?;
103 Ok(())
104}
105
106pub async fn pin_verify(format: &str) -> Result<()> {
108 use ipfrs::{Node, NodeConfig};
109
110 let pb = progress::spinner("Verifying pins");
111 let mut node = Node::new(NodeConfig::default())?;
112 node.start().await?;
113
114 let results = node.pin_verify().await?;
115 progress::finish_spinner_success(&pb, "Verification complete");
116
117 let valid_count = results.iter().filter(|(_, valid)| *valid).count();
118 let invalid_count = results.len() - valid_count;
119
120 match format {
121 "json" => {
122 println!("{{");
123 println!(" \"total\": {},", results.len());
124 println!(" \"valid\": {},", valid_count);
125 println!(" \"invalid\": {}", invalid_count);
126 println!("}}");
127 }
128 _ => {
129 print_header("Pin Verification Results");
130 print_kv("Total pins", &results.len().to_string());
131 print_kv("Valid", &valid_count.to_string());
132 print_kv("Invalid", &invalid_count.to_string());
133
134 if invalid_count > 0 {
135 println!("\nInvalid pins:");
136 for (cid, valid) in &results {
137 if !valid {
138 error(&format!(" {}", cid));
139 }
140 }
141 } else {
142 success("All pins verified successfully");
143 }
144 }
145 }
146
147 node.stop().await?;
148 Ok(())
149}