From 23adaba46e4c8a8e3ce770f78f24641dc0278dd4 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Sun, 12 Apr 2020 23:50:10 -0700 Subject: [PATCH 1/2] add function to get a list of jobs for a project. --- src/gitlab.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/gitlab.rs b/src/gitlab.rs index 63fef6ca..071b9e5c 100644 --- a/src/gitlab.rs +++ b/src/gitlab.rs @@ -1571,6 +1571,17 @@ impl Gitlab { unimplemented!(); } + /// Get a list of jobs for a project. + pub fn jobs(&self, project: ProjectId, params: I) -> GitlabResult> + where + I: IntoIterator, + I::Item: Borrow<(K, V)>, + K: AsRef, + V: AsRef, + { + self.get_paged_with_param(format!("projects/{}/jobs", project), params) + } + /// Get a list of jobs for a pipeline. pub fn pipeline_jobs( &self, -- GitLab From b0bd8a66793694e8e98537cddc67652c12a21df0 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Mon, 13 Apr 2020 02:38:55 -0700 Subject: [PATCH 2/2] add limit parameter to limit the number of server queries This is useful when the server would return a huge number of results but only the first few are actually used --- src/gitlab.rs | 233 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 189 insertions(+), 44 deletions(-) diff --git a/src/gitlab.rs b/src/gitlab.rs index 071b9e5c..3ef404c4 100644 --- a/src/gitlab.rs +++ b/src/gitlab.rs @@ -392,8 +392,9 @@ impl Gitlab { self.get_with_param("user", query_param_slice![]) } - /// Get all user accounts - pub fn users(&self, params: I) -> GitlabResult> + /// Get all user accounts. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. + pub fn users(&self, params: I, limit: Option) -> GitlabResult> where T: UserResult, I: IntoIterator, @@ -401,7 +402,7 @@ impl Gitlab { K: AsRef, V: AsRef, { - self.get_paged_with_param("users", params) + self.get_paged_with_param("users", params, limit) } /// Find a user by id. @@ -422,7 +423,8 @@ impl Gitlab { T: UserResult, N: AsRef, { - let mut users = self.get_paged_with_param("users", &[("username", name.as_ref())])?; + let mut users = + self.get_paged_with_param("users", &[("username", name.as_ref())], Some(1))?; users .pop() .ok_or_else(|| GitlabError::no_such_user(name.as_ref())) @@ -527,19 +529,21 @@ impl Gitlab { } /// Get all accessible projects. - pub fn projects(&self, params: I) -> GitlabResult> + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. + pub fn projects(&self, params: I, limit: Option) -> GitlabResult> where I: IntoIterator, I::Item: Borrow<(K, V)>, K: AsRef, V: AsRef, { - self.get_paged_with_param("projects", params) + self.get_paged_with_param("projects", params, limit) } /// Get all owned projects. - pub fn owned_projects(&self) -> GitlabResult> { - self.get_paged_with_param("projects", &[("owned", "true")]) + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. + pub fn owned_projects(&self, limit: Option) -> GitlabResult> { + self.get_paged_with_param("projects", &[("owned", "true")], limit) } /// Find a project by id. @@ -574,10 +578,12 @@ impl Gitlab { } /// Get all accessible environments. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn environments( &self, project: ProjectId, params: I, + limit: Option, ) -> GitlabResult> where I: IntoIterator, @@ -585,7 +591,7 @@ impl Gitlab { K: AsRef, V: AsRef, { - self.get_paged_with_param(format!("projects/{}/environments", project), params) + self.get_paged_with_param(format!("projects/{}/environments", project), params, limit) } pub fn environment( @@ -641,14 +647,15 @@ impl Gitlab { } /// Get all accessible groups. - pub fn groups(&self, params: I) -> GitlabResult> + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. + pub fn groups(&self, params: I, limit: Option) -> GitlabResult> where I: IntoIterator, I::Item: Borrow<(K, V)>, K: AsRef, V: AsRef, { - self.get_paged_with_param("groups", params) + self.get_paged_with_param("groups", params, limit) } /// Find a group by its name. @@ -661,14 +668,20 @@ impl Gitlab { } /// Get a project's hooks. - pub fn hooks(&self, project: ProjectId, params: I) -> GitlabResult> + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. + pub fn hooks( + &self, + project: ProjectId, + params: I, + limit: Option, + ) -> GitlabResult> where I: IntoIterator, I::Item: Borrow<(K, V)>, K: AsRef, V: AsRef, { - self.get_paged_with_param(format!("projects/{}/hooks", project), params) + self.get_paged_with_param(format!("projects/{}/hooks", project), params, limit) } /// Get a project hook. @@ -747,14 +760,20 @@ impl Gitlab { } /// Get the team members of a group. - pub fn group_members(&self, group: GroupId, params: I) -> GitlabResult> + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. + pub fn group_members( + &self, + group: GroupId, + params: I, + limit: Option, + ) -> GitlabResult> where I: IntoIterator, I::Item: Borrow<(K, V)>, K: AsRef, V: AsRef, { - self.get_paged_with_param(format!("groups/{}/members", group), params) + self.get_paged_with_param(format!("groups/{}/members", group), params, limit) } /// Get a team member of a group. @@ -774,10 +793,12 @@ impl Gitlab { } /// Get the team members of a project. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn project_members( &self, project: ProjectId, params: I, + limit: Option, ) -> GitlabResult> where I: IntoIterator, @@ -785,7 +806,7 @@ impl Gitlab { K: AsRef, V: AsRef, { - self.get_paged_with_param(format!("projects/{}/members", project), params) + self.get_paged_with_param(format!("projects/{}/members", project), params, limit) } /// Get a team member of a project. @@ -854,14 +875,24 @@ impl Gitlab { } /// Get branches for a project. - pub fn branches(&self, project: ProjectId, params: I) -> GitlabResult> + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. + pub fn branches( + &self, + project: ProjectId, + params: I, + limit: Option, + ) -> GitlabResult> where I: IntoIterator, I::Item: Borrow<(K, V)>, K: AsRef, V: AsRef, { - self.get_paged_with_param(format!("projects/{}/repository/branches", project), params) + self.get_paged_with_param( + format!("projects/{}/repository/branches", project), + params, + limit, + ) } /// Get a branch. @@ -960,11 +991,13 @@ impl Gitlab { } /// Get comments on a commit. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn commit_comments( &self, project: ProjectId, commit: C, params: I, + limit: Option, ) -> GitlabResult> where C: AsRef, @@ -980,6 +1013,7 @@ impl Gitlab { commit.as_ref(), ), params, + limit, ) } @@ -1050,11 +1084,13 @@ impl Gitlab { } /// Get the latest statuses of a commit. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn commit_latest_statuses( &self, project: ProjectId, commit: C, params: I, + limit: Option, ) -> GitlabResult> where C: AsRef, @@ -1070,15 +1106,18 @@ impl Gitlab { commit.as_ref(), ), params, + limit, ) } /// Get the latest statuses of a commit. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn commit_latest_statuses_by_name( &self, project: P, commit: C, params: I, + limit: Option, ) -> GitlabResult> where P: AsRef, @@ -1095,14 +1134,17 @@ impl Gitlab { commit.as_ref(), ), params, + limit, ) } - /// Get the all statuses of a commit. + /// Get all statuses of a commit. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn commit_all_statuses( &self, project: ProjectId, commit: C, + limit: Option, ) -> GitlabResult> where C: AsRef, @@ -1114,15 +1156,18 @@ impl Gitlab { commit.as_ref(), ), &[("all", "true")], + limit, ) } /// Get the latest builds of a commit. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn commit_latest_builds( &self, project: ProjectId, commit: C, params: I, + limit: Option, ) -> GitlabResult> where C: AsRef, @@ -1138,11 +1183,18 @@ impl Gitlab { commit.as_ref(), ), params, + limit, ) } - /// Get the all builds of a commit. - pub fn commit_all_builds(&self, project: ProjectId, commit: C) -> GitlabResult> + /// Get all builds of a commit. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. + pub fn commit_all_builds( + &self, + project: ProjectId, + commit: C, + limit: Option, + ) -> GitlabResult> where C: AsRef, { @@ -1153,6 +1205,7 @@ impl Gitlab { commit.as_ref(), ), &[("all", "true")], + limit, ) } @@ -1224,15 +1277,22 @@ impl Gitlab { } /// Get the labels for a project. - pub fn labels(&self, project: ProjectId) -> GitlabResult> { - self.get_paged(format!("projects/{}/labels", project)) + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. + pub fn labels(&self, project: ProjectId, limit: Option) -> GitlabResult> { + self.get_paged(format!("projects/{}/labels", project), limit) } - /// Get the labels with open/closed/merge requests count - pub fn labels_with_counts(&self, project: ProjectId) -> GitlabResult> { + /// Get the labels with open/closed/merge requests count. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. + pub fn labels_with_counts( + &self, + project: ProjectId, + limit: Option, + ) -> GitlabResult> { self.get_paged_with_param( format!("projects/{}/labels", project), &[("with_counts", "true")], + limit, ) } @@ -1242,14 +1302,20 @@ impl Gitlab { } /// Get the issues for a project. - pub fn issues(&self, project: ProjectId, params: I) -> GitlabResult> + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. + pub fn issues( + &self, + project: ProjectId, + params: I, + limit: Option, + ) -> GitlabResult> where I: IntoIterator, I::Item: Borrow<(K, V)>, K: AsRef, V: AsRef, { - self.get_paged_with_param(format!("projects/{}/issues", project), params) + self.get_paged_with_param(format!("projects/{}/issues", project), params, limit) } /// Get issues. @@ -1269,11 +1335,13 @@ impl Gitlab { } /// Get the notes from a issue. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn issue_notes( &self, project: ProjectId, issue: IssueInternalId, params: I, + limit: Option, ) -> GitlabResult> where I: IntoIterator, @@ -1284,15 +1352,18 @@ impl Gitlab { self.get_paged_with_param( format!("projects/{}/issues/{}/notes", project, issue), params, + limit, ) } /// Get the notes from a issue. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn issue_notes_by_name( &self, project: P, issue: IssueInternalId, params: I, + limit: Option, ) -> GitlabResult> where P: AsRef, @@ -1308,6 +1379,7 @@ impl Gitlab { issue, ), params, + limit, ) } @@ -1403,15 +1475,20 @@ impl Gitlab { } /// Get the resource label events from an issue. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn issue_label_events( &self, project: ProjectId, issue: IssueInternalId, + limit: Option, ) -> GitlabResult> { - self.get_paged(format!( - "projects/{}/issues/{}/resource_label_events", - project, issue, - )) + self.get_paged( + format!( + "projects/{}/issues/{}/resource_label_events", + project, issue + ), + limit, + ) } /// Create a note on a issue. @@ -1466,10 +1543,12 @@ impl Gitlab { } /// Get the merge requests for a project. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn merge_requests( &self, project: ProjectId, params: I, + limit: Option, ) -> GitlabResult> where I: IntoIterator, @@ -1477,18 +1556,25 @@ impl Gitlab { K: AsRef, V: AsRef, { - self.get_paged_with_param(format!("projects/{}/merge_requests", project), params) + self.get_paged_with_param( + format!("projects/{}/merge_requests", project), + params, + limit, + ) } /// Get the merge requests with a given state. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn merge_requests_with_state( &self, project: ProjectId, state: MergeRequestStateFilter, + limit: Option, ) -> GitlabResult> { self.get_paged_with_param( format!("projects/{}/merge_requests", project), &[("state", state.as_str())], + limit, ) } @@ -1502,10 +1588,12 @@ impl Gitlab { } /// Get all pipelines for a project. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn pipelines( &self, project: ProjectId, params: I, + limit: Option, ) -> GitlabResult> where I: IntoIterator, @@ -1513,7 +1601,7 @@ impl Gitlab { K: AsRef, V: AsRef, { - self.get_paged_with_param(format!("projects/{}/pipelines", project), params) + self.get_paged_with_param(format!("projects/{}/pipelines", project), params, limit) } /// Get a single pipeline. @@ -1572,22 +1660,30 @@ impl Gitlab { } /// Get a list of jobs for a project. - pub fn jobs(&self, project: ProjectId, params: I) -> GitlabResult> + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. + pub fn jobs( + &self, + project: ProjectId, + params: I, + limit: Option, + ) -> GitlabResult> where I: IntoIterator, I::Item: Borrow<(K, V)>, K: AsRef, V: AsRef, { - self.get_paged_with_param(format!("projects/{}/jobs", project), params) + self.get_paged_with_param(format!("projects/{}/jobs", project), params, limit) } /// Get a list of jobs for a pipeline. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn pipeline_jobs( &self, project: ProjectId, pipeline_id: PipelineId, params: I, + limit: Option, ) -> GitlabResult> where I: IntoIterator, @@ -1598,6 +1694,7 @@ impl Gitlab { self.get_paged_with_param( format!("projects/{}/pipelines/{}/jobs", project, pipeline_id), params, + limit, ) } @@ -1634,11 +1731,13 @@ impl Gitlab { } /// Get the issues that will be closed when a merge request is merged. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn merge_request_closes_issues( &self, project: ProjectId, merge_request: MergeRequestInternalId, params: I, + limit: Option, ) -> GitlabResult> where I: IntoIterator, @@ -1652,15 +1751,18 @@ impl Gitlab { project, merge_request, ), params, + limit, ) } /// Get the discussions from a merge request. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn merge_request_discussions( &self, project: ProjectId, merge_request: MergeRequestInternalId, params: I, + limit: Option, ) -> GitlabResult> where I: IntoIterator, @@ -1674,15 +1776,18 @@ impl Gitlab { project, merge_request, ), params, + limit, ) } /// Get the notes from a merge request. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn merge_request_notes( &self, project: ProjectId, merge_request: MergeRequestInternalId, params: I, + limit: Option, ) -> GitlabResult> where I: IntoIterator, @@ -1696,15 +1801,18 @@ impl Gitlab { project, merge_request, ), params, + limit, ) } /// Get the notes from a merge request. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn merge_request_notes_by_name( &self, project: P, merge_request: MergeRequestInternalId, params: I, + limit: Option, ) -> GitlabResult> where P: AsRef, @@ -1720,6 +1828,7 @@ impl Gitlab { merge_request, ), params, + limit, ) } @@ -1759,11 +1868,13 @@ impl Gitlab { } /// Get the awards for a merge request. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn merge_request_awards( &self, project: ProjectId, merge_request: MergeRequestInternalId, params: I, + limit: Option, ) -> GitlabResult> where I: IntoIterator, @@ -1777,15 +1888,18 @@ impl Gitlab { project, merge_request, ), params, + limit, ) } /// Get the awards for a merge request. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn merge_request_awards_by_name( &self, project: P, merge_request: MergeRequestInternalId, params: I, + limit: Option, ) -> GitlabResult> where P: AsRef, @@ -1801,16 +1915,19 @@ impl Gitlab { merge_request, ), params, + limit, ) } /// Get the awards for a merge request note. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn merge_request_note_awards( &self, project: ProjectId, merge_request: MergeRequestInternalId, note: NoteId, params: I, + limit: Option, ) -> GitlabResult> where I: IntoIterator, @@ -1824,16 +1941,19 @@ impl Gitlab { project, merge_request, note, ), params, + limit, ) } /// Get the awards for a merge request note. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn merge_request_note_awards_by_name( &self, project: P, merge_request: MergeRequestInternalId, note: NoteId, params: I, + limit: Option, ) -> GitlabResult> where P: AsRef, @@ -1850,19 +1970,25 @@ impl Gitlab { note, ), params, + limit, ) } /// Get the resource label events from a merge request. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn merge_request_label_events( &self, project: ProjectId, merge_request: MergeRequestInternalId, + limit: Option, ) -> GitlabResult> { - self.get_paged(format!( - "projects/{}/merge_requests/{}/resource_label_events", - project, merge_request, - )) + self.get_paged( + format!( + "projects/{}/merge_requests/{}/resource_label_events", + project, merge_request, + ), + limit, + ) } pub fn create_merge_request_discussion( @@ -1877,6 +2003,7 @@ impl Gitlab { ); self.post_with_param(path, &[("body", content)]) } + /// Create a note on a merge request. pub fn create_merge_request_note( &self, @@ -1946,11 +2073,13 @@ impl Gitlab { } /// Get issues closed by a merge request. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn get_issues_closed_by_merge_request( &self, project: ProjectId, merge_request: MergeRequestInternalId, params: I, + limit: Option, ) -> GitlabResult> where I: IntoIterator, @@ -1964,15 +2093,18 @@ impl Gitlab { project, merge_request, ), params, + limit, ) } /// Get issues closed by a merge request. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. pub fn get_issues_closed_by_merge_request_by_name( &self, project: P, merge_request: MergeRequestInternalId, params: I, + limit: Option, ) -> GitlabResult> where P: AsRef, @@ -1988,6 +2120,7 @@ impl Gitlab { merge_request, ), params, + limit, ) } @@ -2188,17 +2321,24 @@ impl Gitlab { self.send(self.client.put(full_url).form(¶m)) } - /// Handle paginated queries. Returns all results. - fn get_paged(&self, url: U) -> GitlabResult> + /// Handle paginated queries. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. + fn get_paged(&self, url: U, limit: Option) -> GitlabResult> where T: DeserializeOwned, U: AsRef, { - self.get_paged_with_param(url, query_param_slice![]) + self.get_paged_with_param(url, query_param_slice![], limit) } - /// Handle paginated queries with query parameters. Returns all results. - fn get_paged_with_param(&self, url: U, params: I) -> GitlabResult> + /// Handle paginated queries with query parameters. + /// Returns all results if `limit` is `None`, otherwise up to `limit` results. + fn get_paged_with_param( + &self, + url: U, + params: I, + limit: Option, + ) -> GitlabResult> where T: DeserializeOwned, U: AsRef, @@ -2207,6 +2347,7 @@ impl Gitlab { K: AsRef, V: AsRef, { + let limit = limit.unwrap_or(usize::max_value()); let mut page_num = 1; let per_page = 100; let per_page_str = &format!("{}", per_page); @@ -2227,6 +2368,10 @@ impl Gitlab { let page_len = page.len(); results.extend(page); + if results.len() >= limit { + results.drain(limit..); + break; + } // Gitlab used to have issues returning paginated results; these have been fixed since, // but if it is needed, the bug manifests as Gitlab returning *all* results instead of // just the requested results. This can cause an infinite loop here if the number of -- GitLab