git_stk/commands/
status.rs1use anyhow::Result;
2use clap_complete::engine::ArgValueCompleter;
3
4use crate::commands::Run;
5use crate::completions;
6use crate::providers::{ReviewState, detect_provider, review_provider};
7use crate::{git, stack};
8
9#[derive(Debug, clap::Args)]
11pub struct Status {
12 #[arg(add = ArgValueCompleter::new(completions::branch_candidates))]
13 branch: Option<String>,
14}
15
16impl Run for Status {
17 fn run(self) -> Result<()> {
18 print_status(self.branch.as_deref())
19 }
20}
21
22pub fn print_status(branch: Option<&str>) -> Result<()> {
23 let branch = branch
24 .map(str::to_owned)
25 .map_or_else(git::current_branch, Ok)?;
26 let parent = stack::parent_for_branch(&branch)?;
27 let children = stack::children_for_branch(&branch)?;
28
29 println!("branch: {branch}");
30 match parent.as_deref() {
31 Some(parent) => println!("parent: {parent}"),
32 None => println!("parent: none"),
33 }
34 if children.is_empty() {
35 println!("children: none");
36 } else {
37 println!("children: {}", children.join(", "));
38 }
39
40 let provider = detect_provider()?;
41 println!("provider: {} ({})", provider.kind, provider.source);
42 let review_provider = review_provider(provider.kind);
43
44 let review = review_provider.review_for_branch_including_closed(&branch)?;
47 match &review {
48 Some(review) => {
49 println!(
50 "review: {} {} {} -> {}",
51 review.id, review.state, review.branch, review.base
52 );
53 println!("url: {}", review.url);
54
55 if let Some(parent) = parent.as_deref()
56 && parent != review.base
57 {
58 println!(
59 "warning: review base is {}, local parent is {parent} - run `git stk submit`",
60 review.base
61 );
62 }
63 }
64 None => println!("review: none"),
65 }
66
67 let mut hints = Vec::new();
70 match &review {
71 Some(review) if review.state == ReviewState::Merged => {
72 hints.push(format!(
73 "review {} is merged - run `git stk sync`",
74 review.id
75 ));
76 }
77 Some(review) if review.state == ReviewState::Closed => {
78 hints.push(format!(
79 "review {} was closed without merging - `git stk submit` opens a new review",
80 review.id
81 ));
82 }
83 _ => {}
84 }
85 if let Some(parent) = parent.as_deref() {
86 match review_provider.review_for_branch_including_closed(parent) {
87 Ok(Some(parent_review)) if parent_review.branch == parent => {
88 match parent_review.state {
89 ReviewState::Merged => hints.push(format!(
90 "parent review {} is merged - run `git stk sync`",
91 parent_review.id
92 )),
93 ReviewState::Closed => hints.push(format!(
94 "parent review {} was closed without merging - \
95 retarget {branch} with `git stk adopt`",
96 parent_review.id
97 )),
98 _ => {}
99 }
100 }
101 _ => {}
102 }
103
104 if hints.is_empty()
105 && let Some(hint) = stack::behind_parent_hint(&branch, parent)
106 {
107 hints.push(hint);
108 }
109 }
110 for hint in hints {
111 println!("hint: {hint}");
112 }
113
114 Ok(())
115}