Skip to main content

gitee_cli_rs/api/
mod.rs

1pub mod client;
2pub mod collaborators;
3pub mod gists;
4pub mod issues;
5pub mod labels;
6pub mod pulls;
7pub mod milestones;
8pub mod releases;
9pub mod repos;
10pub mod search;
11pub mod users;
12pub mod webhooks;
13
14use crate::models::{Comment, PrComment};
15
16/// Outcome of an idempotent mutating call: did the resource change, or was it
17/// already in the requested state? The wrapped object is the current state of
18/// the resource either way, so callers can render it consistently.
19#[derive(Debug, Clone)]
20pub enum StateChange<T> {
21    Changed(T),
22    Already(T),
23}
24
25/// Minimal view of a comment for `--last` resolution (author + created_at).
26pub trait AuthoredComment {
27    fn author_login(&self) -> Option<&str>;
28    fn created_at_str(&self) -> Option<&str>;
29}
30
31impl AuthoredComment for Comment {
32    fn author_login(&self) -> Option<&str> {
33        self.user.as_ref().map(|u| u.login.as_str())
34    }
35    fn created_at_str(&self) -> Option<&str> {
36        self.created_at.as_deref()
37    }
38}
39
40impl AuthoredComment for PrComment {
41    fn author_login(&self) -> Option<&str> {
42        self.user.as_ref().map(|u| u.login.as_str())
43    }
44    fn created_at_str(&self) -> Option<&str> {
45        self.created_at.as_deref()
46    }
47}
48
49/// Pick the comment by `login` with the greatest `created_at` string.
50/// ISO-8601 timestamps from Gitee sort lexicographically.
51pub fn resolve_latest_comment<'a, T: AuthoredComment>(
52    comments: &'a [T],
53    login: &str,
54) -> Option<&'a T> {
55    comments
56        .iter()
57        .filter(|c| c.author_login() == Some(login))
58        .max_by_key(|c| c.created_at_str().unwrap_or(""))
59}
60
61impl<T> StateChange<T> {
62    pub fn into_inner(self) -> T {
63        match self {
64            StateChange::Changed(t) | StateChange::Already(t) => t,
65        }
66    }
67
68    pub fn was_changed(&self) -> bool {
69        matches!(self, StateChange::Changed(_))
70    }
71}