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