sift_queue/cli/commands/
add.rs1use crate::queue::{Queue, Source};
2use crate::AddArgs;
3use anyhow::Result;
4use std::io::Read;
5use std::path::PathBuf;
6
7pub fn execute(args: &AddArgs, queue_path: PathBuf) -> Result<i32> {
9 let queue = Queue::new(queue_path);
10
11 let mut sources: Vec<Source> = Vec::new();
12
13 for path in &args.diff {
14 sources.push(Source {
15 type_: "diff".to_string(),
16 path: Some(path.clone()),
17 content: None,
18 session_id: None,
19 });
20 }
21
22 for path in &args.file {
23 sources.push(Source {
24 type_: "file".to_string(),
25 path: Some(path.clone()),
26 content: None,
27 session_id: None,
28 });
29 }
30
31 for text in &args.text {
32 sources.push(Source {
33 type_: "text".to_string(),
34 path: None,
35 content: Some(text.clone()),
36 session_id: None,
37 });
38 }
39
40 for path in &args.directory {
41 sources.push(Source {
42 type_: "directory".to_string(),
43 path: Some(path.clone()),
44 content: None,
45 session_id: None,
46 });
47 }
48
49 if let Some(ref stdin_type) = args.stdin {
50 let mut content = String::new();
51 std::io::stdin().read_to_string(&mut content)?;
52 sources.push(Source {
53 type_: stdin_type.clone(),
54 path: None,
55 content: Some(content),
56 session_id: None,
57 });
58 }
59
60 let has_source = !sources.is_empty();
61 let has_description = args.description.is_some();
62 let has_title = args.title.is_some();
63 let has_metadata = args.metadata.is_some();
64
65 if !has_source && !has_description && !has_title && !has_metadata {
66 eprintln!(
67 "Error: At least one of --description, --title, --metadata, or a source is required"
68 );
69 eprintln!("Use --diff, --file, --text, --directory, --stdin, --description, --title, or --metadata");
70 return Ok(1);
71 }
72
73 let metadata = match &args.metadata {
74 Some(json_str) => match serde_json::from_str(json_str) {
75 Ok(v) => v,
76 Err(e) => {
77 eprintln!("Error: Invalid JSON for metadata: {}", e);
78 return Ok(1);
79 }
80 },
81 None => serde_json::Value::Object(serde_json::Map::new()),
82 };
83
84 let blocked_by: Vec<String> = match &args.blocked_by {
85 Some(ids) => ids
86 .split(',')
87 .map(|s| s.trim().to_string())
88 .filter(|s| !s.is_empty())
89 .collect(),
90 None => Vec::new(),
91 };
92
93 let item = queue.push_with_description(
94 sources,
95 args.title.clone(),
96 args.description.clone(),
97 metadata,
98 None,
99 blocked_by,
100 )?;
101
102 if args.json {
103 let json = serde_json::to_string_pretty(&item.to_json_value())?;
104 println!("{}", json);
105 } else {
106 println!("{}", item.id);
107 eprintln!(
108 "Added item {} with {} source(s)",
109 item.id,
110 item.sources.len()
111 );
112 }
113
114 Ok(0)
115}