Skip to main content

mesa_dev/resources/
commits.rs

1//! Commit operations.
2//!
3//! Access via [`MesaClient::commits`](crate::MesaClient::commits):
4//!
5//! ```rust,no_run
6//! # use mesa_dev::{Mesa, MesaError};
7//! # async fn run() -> Result<(), MesaError> {
8//! # let client = Mesa::new("key");
9//! let commit = client.commits("my-org", "my-repo").get("abc123").await?;
10//! println!("Commit: {}", commit.message);
11//! # Ok(())
12//! # }
13//! ```
14
15use std::sync::Arc;
16
17use http::Method;
18
19use crate::client::MesaClient;
20use crate::error::MesaError;
21use crate::http_client::HttpClient;
22use crate::models::{
23    Commit, CommitSummary, CreateCommitRequest, CreateCommitWithLfsRequest, ListCommitsResponse,
24    PaginationParams,
25};
26use crate::pagination::PageStream;
27
28/// Query parameters for listing commits.
29///
30/// # Example
31///
32/// ```rust
33/// use mesa_dev::resources::ListCommitsParams;
34///
35/// let params = ListCommitsParams {
36///     ref_: Some("main".to_owned()),
37///     ..Default::default()
38/// };
39/// ```
40#[derive(Debug, Clone, Default)]
41pub struct ListCommitsParams {
42    /// Pagination parameters.
43    pub pagination: PaginationParams,
44    /// Optional ref (branch name or SHA) to list commits from.
45    pub ref_: Option<String>,
46}
47
48/// Operations on commits within a repository.
49pub struct CommitsResource<'c, C: HttpClient> {
50    client: &'c MesaClient<C>,
51    org: String,
52    repo: String,
53}
54
55impl<'c, C: HttpClient> CommitsResource<'c, C> {
56    pub(crate) fn new(client: &'c MesaClient<C>, org: String, repo: String) -> Self {
57        Self { client, org, repo }
58    }
59
60    /// Create a new commit.
61    ///
62    /// # Errors
63    ///
64    /// Returns [`MesaError`] if the API request fails.
65    pub async fn create(&self, req: &CreateCommitRequest) -> Result<CommitSummary, MesaError> {
66        let path = format!("/{}/{}/commits", self.org, self.repo);
67        self.client
68            .request(Method::POST, &path, &[], Some(req))
69            .await
70    }
71
72    /// List commits with pagination and optional ref filter.
73    ///
74    /// # Errors
75    ///
76    /// Returns [`MesaError`] if the API request fails.
77    pub async fn list(&self, params: &ListCommitsParams) -> Result<ListCommitsResponse, MesaError> {
78        let path = format!("/{}/{}/commits", self.org, self.repo);
79        let mut query: Vec<(&str, String)> = Vec::new();
80        if let Some(ref cursor) = params.pagination.cursor {
81            query.push(("cursor", cursor.clone()));
82        }
83        if let Some(limit) = params.pagination.limit {
84            query.push(("limit", limit.to_string()));
85        }
86        if let Some(ref r) = params.ref_ {
87            query.push(("ref", r.clone()));
88        }
89        let query_refs: Vec<(&str, &str)> = query.iter().map(|(k, v)| (*k, v.as_str())).collect();
90        self.client
91            .request(Method::GET, &path, &query_refs, None::<&()>)
92            .await
93    }
94
95    /// Return a [`PageStream`] that iterates over all commits.
96    ///
97    /// Optionally filter by ref (branch name or SHA).
98    #[must_use]
99    pub fn list_all(&self, ref_: Option<&str>) -> PageStream<C, ListCommitsResponse> {
100        let path = format!("/{}/{}/commits", self.org, self.repo);
101        let extra = match ref_ {
102            Some(r) => vec![("ref".to_owned(), r.to_owned())],
103            None => Vec::new(),
104        };
105        PageStream::new(Arc::clone(&self.client.inner), path, extra)
106    }
107
108    /// Get a single commit by SHA.
109    ///
110    /// # Errors
111    ///
112    /// Returns [`MesaError`] if the API request fails.
113    pub async fn get(&self, sha: &str) -> Result<Commit, MesaError> {
114        let path = format!("/{}/{}/commits/{sha}", self.org, self.repo);
115        self.client
116            .request(Method::GET, &path, &[], None::<&()>)
117            .await
118    }
119
120    /// Create a new commit with flexible file types (including LFS).
121    ///
122    /// Use this method when you need to include LFS file references in your commit.
123    ///
124    /// # Errors
125    ///
126    /// Returns [`MesaError`] if the API request fails.
127    ///
128    /// # Example
129    ///
130    /// ```rust,no_run
131    /// # use mesa_dev::{Mesa, MesaError};
132    /// # async fn run() -> Result<(), MesaError> {
133    /// # let client = Mesa::new("key");
134    /// use mesa_dev::models::{Author, CommitFileChange, CreateCommitWithLfsRequest};
135    ///
136    /// let commit = client.commits("my-org", "my-repo")
137    ///     .create_with_lfs(&CreateCommitWithLfsRequest {
138    ///         branch: "main".to_owned(),
139    ///         message: "Add large file".to_owned(),
140    ///         author: Author {
141    ///             name: "Bot".to_owned(),
142    ///             email: "bot@example.com".to_owned(),
143    ///             date: None,
144    ///         },
145    ///         files: vec![
146    ///             CommitFileChange::lfs("models/large.bin", "abc123...", 12345678),
147    ///         ],
148    ///         base_sha: None,
149    ///     })
150    ///     .await?;
151    /// # Ok(())
152    /// # }
153    /// ```
154    pub async fn create_with_lfs(
155        &self,
156        req: &CreateCommitWithLfsRequest,
157    ) -> Result<CommitSummary, MesaError> {
158        let path = format!("/{}/{}/commits", self.org, self.repo);
159        self.client
160            .request(Method::POST, &path, &[], Some(req))
161            .await
162    }
163}