@@ -401,9 +401,6 @@ fn main() {
return;
}
- // The number of patches tested so far. If --count isn't provided, this is unused.
- let mut patch_count = 0;
-
/*
* Poll Patchwork for new patches.
* If the patch is standalone (not part of a series), apply it.
@@ -411,9 +408,19 @@ fn main() {
* Spawn tests.
*/
'daemon: loop {
- let patch_list = patchwork
- .get_patch_query(&args.flag_project)
- .unwrap_or_else(|err| panic!("Failed to obtain patch list: {}", err));
+ let patch_list;
+
+ // TODO: This is hacky and we should refactor out daemon vs patch/count
+ // mode
+ if args.flag_count > 0 {
+ patch_list = patchwork
+ .get_patch_query_num(&args.flag_project, args.flag_count as usize)
+ .unwrap_or_else(|err| panic!("Failed to obtain patch list: {}", err));
+ } else {
+ patch_list = patchwork
+ .get_patch_query(&args.flag_project)
+ .unwrap_or_else(|err| panic!("Failed to obtain patch list: {}", err));
+ }
info!("snowpatch is ready to test new revisions from Patchwork.");
for patch in patch_list {
// If it's already been tested, we can skip it
@@ -481,13 +488,9 @@ fn main() {
patchwork.post_test_result(result, &patch.checks).unwrap();
}
}
- if args.flag_count > 0 {
- patch_count += 1;
- debug!("Tested {} patches out of {}", patch_count, args.flag_count);
- if patch_count >= args.flag_count {
- break 'daemon;
- }
- }
+ }
+ if args.flag_count > 0 {
+ break;
}
info!("Finished testing new revisions, sleeping.");
thread::sleep(Duration::new(settings.patchwork.polling_interval * 60, 0));
@@ -25,7 +25,9 @@ use std::result::Result;
use tempdir::TempDir;
use reqwest;
-use reqwest::header::{qitem, Accept, Authorization, Basic, Connection, ContentType, Headers};
+use reqwest::header::{
+ qitem, Accept, Authorization, Basic, Connection, ContentType, Headers, Link, RelationType,
+};
use reqwest::Client;
use reqwest::Response;
use reqwest::StatusCode;
@@ -306,6 +308,43 @@ impl PatchworkServer {
.unwrap_or_else(|err| panic!("Failed to connect to Patchwork: {}", err)))
}
+ fn get_next_link(&self, resp: &Response) -> Option<String> {
+ let next = resp.headers().get::<Link>()?;
+ for val in next.values() {
+ if let Some(rel) = val.rel() {
+ if rel.iter().any(|reltype| reltype == &RelationType::Next) {
+ return Some(val.link().to_string());
+ }
+ }
+ }
+ None
+ }
+
+ pub fn get_patch_query_num(
+ &self,
+ project: &str,
+ num_patches: usize,
+ ) -> Result<Vec<Patch>, serde_json::Error> {
+ let mut list: Vec<Patch> = vec![];
+ let mut url = Some(format!(
+ "{}{}/patches/{}&project={}",
+ &self.url, PATCHWORK_API, PATCHWORK_QUERY, project
+ ));
+
+ while let Some(real_url) = url {
+ let resp = self.get_url(&real_url)
+ .unwrap_or_else(|err| panic!("Failed to connect to Patchwork: {}", err));
+ url = self.get_next_link(&resp);
+ let new_patches: Vec<Patch> = serde_json::from_reader(resp)?;
+ list.extend(new_patches);
+ if list.len() >= num_patches {
+ break;
+ }
+ }
+ list.truncate(num_patches);
+ Ok(list)
+ }
+
pub fn get_patch_dependencies(&self, patch: &Patch) -> Vec<Patch> {
// We assume the list of patches in a series are in order.
let mut dependencies: Vec<Patch> = vec![];
Add support for pagination when using --count. We extract the Link header from the Patchwork response to find the correct URL for the next page. The pagination is potentially racy, as new patches could come in and disturb the ordering, but this is a limitation on the Patchwork side at present and is unlikely to be a significant problem. Closes: #17 ("Enable the ability to go to page 2 (and beyond) of Patchwork results") Signed-off-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com> --- src/main.rs | 29 ++++++++++++++++------------- src/patchwork.rs | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 14 deletions(-)