gh_cli_rs/commands/
pr.rs

1use crate::command::{BaseCommand, CommandBuilder, GhCommand};
2use crate::error::Result;
3use crate::executor::GhExecutor;
4use std::sync::Arc;
5
6/// Pull request commands namespace
7#[derive(Clone)]
8pub struct PrCommands {
9    executor: Arc<GhExecutor>,
10}
11
12impl PrCommands {
13    pub(crate) fn new(executor: Arc<GhExecutor>) -> Self {
14        Self { executor }
15    }
16
17    /// Create a new pull request
18    pub fn create(&self) -> PrCreateCommand {
19        PrCreateCommand::new(self.executor.clone())
20    }
21
22    /// List pull requests
23    pub fn list(&self) -> PrListCommand {
24        PrListCommand::new(self.executor.clone())
25    }
26
27    /// View a pull request
28    pub fn view(&self, number: u32) -> PrViewCommand {
29        PrViewCommand::new(self.executor.clone(), number)
30    }
31
32    /// Checkout a pull request
33    pub fn checkout(&self, number: u32) -> PrCheckoutCommand {
34        PrCheckoutCommand::new(self.executor.clone(), number)
35    }
36
37    /// Merge a pull request
38    pub fn merge(&self, number: u32) -> PrMergeCommand {
39        PrMergeCommand::new(self.executor.clone(), number)
40    }
41
42    /// Close a pull request
43    pub fn close(&self, number: u32) -> PrCloseCommand {
44        PrCloseCommand::new(self.executor.clone(), number)
45    }
46}
47
48/// Command for creating a pull request
49pub struct PrCreateCommand {
50    executor: Arc<GhExecutor>,
51    cmd: BaseCommand,
52}
53
54impl PrCreateCommand {
55    fn new(executor: Arc<GhExecutor>) -> Self {
56        Self {
57            executor,
58            cmd: BaseCommand::with_subcommands(&["pr", "create"]),
59        }
60    }
61
62    /// Set the PR title
63    pub fn title(mut self, title: &str) -> Self {
64        self.cmd = self.cmd.option("--title", title);
65        self
66    }
67
68    /// Set the PR body
69    pub fn body(mut self, body: &str) -> Self {
70        self.cmd = self.cmd.option("--body", body);
71        self
72    }
73
74    /// Set the base branch
75    pub fn base(mut self, base: &str) -> Self {
76        self.cmd = self.cmd.option("--base", base);
77        self
78    }
79
80    /// Set the head branch
81    pub fn head(mut self, head: &str) -> Self {
82        self.cmd = self.cmd.option("--head", head);
83        self
84    }
85
86    /// Mark as draft
87    pub fn draft(mut self) -> Self {
88        self.cmd = self.cmd.flag("--draft");
89        self
90    }
91
92    /// Open in web browser
93    pub fn web(mut self) -> Self {
94        self.cmd = self.cmd.flag("--web");
95        self
96    }
97
98    /// Execute the create command
99    pub fn execute(&self) -> Result<String> {
100        GhCommand::execute(self, self.executor.as_ref())
101    }
102}
103
104impl GhCommand for PrCreateCommand {
105    fn build_args(&self) -> Vec<String> {
106        self.cmd.build_args()
107    }
108}
109
110/// Command for listing pull requests
111pub struct PrListCommand {
112    executor: Arc<GhExecutor>,
113    cmd: BaseCommand,
114}
115
116impl PrListCommand {
117    fn new(executor: Arc<GhExecutor>) -> Self {
118        Self {
119            executor,
120            cmd: BaseCommand::with_subcommands(&["pr", "list"]),
121        }
122    }
123
124    /// Filter by state (open, closed, merged, all)
125    pub fn state(mut self, state: &str) -> Self {
126        self.cmd = self.cmd.option("--state", state);
127        self
128    }
129
130    /// Limit the number of results
131    pub fn limit(mut self, limit: u32) -> Self {
132        self.cmd = self.cmd.option("--limit", &limit.to_string());
133        self
134    }
135
136    /// Filter by author
137    pub fn author(mut self, author: &str) -> Self {
138        self.cmd = self.cmd.option("--author", author);
139        self
140    }
141
142    /// Execute and get raw output
143    pub fn execute(&self) -> Result<String> {
144        GhCommand::execute(self, self.executor.as_ref())
145    }
146}
147
148impl GhCommand for PrListCommand {
149    fn build_args(&self) -> Vec<String> {
150        self.cmd.build_args()
151    }
152}
153
154/// Command for viewing a pull request
155pub struct PrViewCommand {
156    executor: Arc<GhExecutor>,
157    cmd: BaseCommand,
158}
159
160impl PrViewCommand {
161    fn new(executor: Arc<GhExecutor>, number: u32) -> Self {
162        Self {
163            executor,
164            cmd: BaseCommand::with_subcommands(&["pr", "view"]).arg(&number.to_string()),
165        }
166    }
167
168    /// Open in web browser
169    pub fn web(mut self) -> Self {
170        self.cmd = self.cmd.flag("--web");
171        self
172    }
173
174    /// Execute and get raw output
175    pub fn execute(&self) -> Result<String> {
176        GhCommand::execute(self, self.executor.as_ref())
177    }
178}
179
180impl GhCommand for PrViewCommand {
181    fn build_args(&self) -> Vec<String> {
182        self.cmd.build_args()
183    }
184}
185
186/// Command for checking out a pull request
187pub struct PrCheckoutCommand {
188    executor: Arc<GhExecutor>,
189    cmd: BaseCommand,
190}
191
192impl PrCheckoutCommand {
193    fn new(executor: Arc<GhExecutor>, number: u32) -> Self {
194        Self {
195            executor,
196            cmd: BaseCommand::with_subcommands(&["pr", "checkout"]).arg(&number.to_string()),
197        }
198    }
199
200    /// Execute the checkout command
201    pub fn execute(&self) -> Result<String> {
202        GhCommand::execute(self, self.executor.as_ref())
203    }
204}
205
206impl GhCommand for PrCheckoutCommand {
207    fn build_args(&self) -> Vec<String> {
208        self.cmd.build_args()
209    }
210}
211
212/// Command for merging a pull request
213pub struct PrMergeCommand {
214    executor: Arc<GhExecutor>,
215    cmd: BaseCommand,
216}
217
218impl PrMergeCommand {
219    fn new(executor: Arc<GhExecutor>, number: u32) -> Self {
220        Self {
221            executor,
222            cmd: BaseCommand::with_subcommands(&["pr", "merge"]).arg(&number.to_string()),
223        }
224    }
225
226    /// Use merge commit
227    pub fn merge(mut self) -> Self {
228        self.cmd = self.cmd.flag("--merge");
229        self
230    }
231
232    /// Use squash merge
233    pub fn squash(mut self) -> Self {
234        self.cmd = self.cmd.flag("--squash");
235        self
236    }
237
238    /// Use rebase merge
239    pub fn rebase(mut self) -> Self {
240        self.cmd = self.cmd.flag("--rebase");
241        self
242    }
243
244    /// Auto-merge when requirements are met
245    pub fn auto(mut self) -> Self {
246        self.cmd = self.cmd.flag("--auto");
247        self
248    }
249
250    /// Execute the merge command
251    pub fn execute(&self) -> Result<String> {
252        GhCommand::execute(self, self.executor.as_ref())
253    }
254}
255
256impl GhCommand for PrMergeCommand {
257    fn build_args(&self) -> Vec<String> {
258        self.cmd.build_args()
259    }
260}
261
262/// Command for closing a pull request
263pub struct PrCloseCommand {
264    executor: Arc<GhExecutor>,
265    cmd: BaseCommand,
266}
267
268impl PrCloseCommand {
269    fn new(executor: Arc<GhExecutor>, number: u32) -> Self {
270        Self {
271            executor,
272            cmd: BaseCommand::with_subcommands(&["pr", "close"]).arg(&number.to_string()),
273        }
274    }
275
276    /// Delete the branch after closing
277    pub fn delete_branch(mut self) -> Self {
278        self.cmd = self.cmd.flag("--delete-branch");
279        self
280    }
281
282    /// Execute the close command
283    pub fn execute(&self) -> Result<String> {
284        GhCommand::execute(self, self.executor.as_ref())
285    }
286}
287
288impl GhCommand for PrCloseCommand {
289    fn build_args(&self) -> Vec<String> {
290        self.cmd.build_args()
291    }
292}