From 162c89e4d9ad6c0029eeb39e7d4200bbfca501ca Mon Sep 17 00:00:00 2001 From: MordechaiHadad Date: Sun, 12 Nov 2023 16:59:02 +0200 Subject: [PATCH] change: now handles when the rate limit has been reached --- src/github_requests.rs | 80 +++++++++++++++++++++++++++++++++ src/handlers/install_handler.rs | 7 +-- src/helpers/version/mod.rs | 4 +- src/helpers/version/nightly.rs | 54 +--------------------- src/helpers/version/types.rs | 11 +---- src/main.rs | 1 + 6 files changed, 90 insertions(+), 67 deletions(-) create mode 100644 src/github_requests.rs diff --git a/src/github_requests.rs b/src/github_requests.rs new file mode 100644 index 0000000..ffa90f9 --- /dev/null +++ b/src/github_requests.rs @@ -0,0 +1,80 @@ +use anyhow::{anyhow, Result}; +use chrono::{DateTime, Utc}; +use reqwest::Client; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct UpstreamVersion { + pub tag_name: String, + pub target_commitish: Option, + pub published_at: DateTime, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct RepoCommit { + pub commit: Commit, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Commit { + pub author: CommitAuthor, + pub message: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct CommitAuthor { + pub name: String, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct ErrorResponse { + pub message: String, + pub documentation_url: String, +} + +pub async fn get_upstream_nightly(client: &Client) -> Result { + let response = client + .get("https://api.github.com/repos/neovim/neovim/releases/tags/nightly") + .header("user-agent", "bob") + .header("Accept", "application/vnd.github.v3+json") + .send() + .await? + .text() + .await?; + + deserialize_response(response) +} + +pub async fn get_commits_for_nightly( + client: &Client, + since: &DateTime, + until: &DateTime, +) -> Result> { + let response = client + .get(format!( + "https://api.github.com/repos/neovim/neovim/commits?since={since}&until={until}&per_page=100")) + .header("user-agent", "bob") + .header("Accept", "application/vnd.github.v3+json") + .send() + .await? + .text() + .await?; + + deserialize_response(response) +} + +pub fn deserialize_response(response: String) -> Result { + let value: serde_json::Value = serde_json::from_str(&response)?; + + if let Some(_) = value.get("message") { + let result: ErrorResponse = serde_json::from_value(value)?; + + if result.documentation_url.contains("rate-limiting") { + return Err(anyhow!("Github API rate limit has been reach, either wait an hour or checkout https://github.com/MordechaiHadad/bob#increasing-github-rate-limit")); + } + + return Err(anyhow!(result.message)); + } + + Ok(serde_json::from_value(value)?) +} diff --git a/src/handlers/install_handler.rs b/src/handlers/install_handler.rs index 0089002..5742ded 100644 --- a/src/handlers/install_handler.rs +++ b/src/handlers/install_handler.rs @@ -1,7 +1,8 @@ use crate::config::Config; +use crate::github_requests::{get_upstream_nightly, UpstreamVersion, get_commits_for_nightly}; use crate::helpers::directories::get_downloads_directory; -use crate::helpers::version::nightly::{get_commits_for_nightly, produce_nightly_vec}; -use crate::helpers::version::types::{LocalVersion, ParsedVersion, UpstreamVersion, VersionType}; +use crate::helpers::version::nightly::produce_nightly_vec; +use crate::helpers::version::types::{LocalVersion, ParsedVersion, VersionType}; use crate::helpers::{self, directories, filesystem, handle_subprocess, unarchive}; use anyhow::{anyhow, Result}; use futures_util::stream::StreamExt; @@ -42,7 +43,7 @@ pub async fn start( } let nightly_version = if version.version_type == VersionType::Nightly { - Some(helpers::version::nightly::get_upstream_nightly(client).await?) + Some(get_upstream_nightly(client).await?) } else { None }; diff --git a/src/helpers/version/mod.rs b/src/helpers/version/mod.rs index 0acadb2..775b0e0 100644 --- a/src/helpers/version/mod.rs +++ b/src/helpers/version/mod.rs @@ -3,7 +3,7 @@ pub mod types; use self::types::{ParsedVersion, VersionType}; use super::directories; -use crate::{config::Config, helpers::version::types::UpstreamVersion}; +use crate::{config::Config, github_requests::{UpstreamVersion, deserialize_response}}; use anyhow::{anyhow, Context, Result}; use regex::Regex; use reqwest::Client; @@ -125,7 +125,7 @@ async fn search_stable_version(client: &Client) -> Result { .text() .await?; - let versions: Vec = serde_json::from_str(&response)?; + let versions: Vec = deserialize_response(response, )?; let stable_release = versions .iter() .find(|v| v.tag_name == "stable") diff --git a/src/helpers/version/nightly.rs b/src/helpers/version/nightly.rs index 54c48f7..4357f00 100644 --- a/src/helpers/version/nightly.rs +++ b/src/helpers/version/nightly.rs @@ -1,42 +1,10 @@ use anyhow::{anyhow, Result}; -use chrono::{DateTime, Utc}; use regex::Regex; -use reqwest::Client; -use serde::{Deserialize, Serialize}; use tokio::fs; -use super::types::{LocalNightly, UpstreamVersion}; -use crate::{config::Config, helpers::directories}; +use super::types::LocalNightly; +use crate::{config::Config, helpers::directories, github_requests::UpstreamVersion}; -#[derive(Serialize, Deserialize, Debug)] -pub struct RepoCommit { - pub commit: Commit, -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct Commit { - pub author: CommitAuthor, - pub message: String, -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct CommitAuthor { - pub name: String, -} - -pub async fn get_upstream_nightly(client: &Client) -> Result { - let response = client - .get("https://api.github.com/repos/neovim/neovim/releases/tags/nightly") - .header("user-agent", "bob") - .header("Accept", "application/vnd.github.v3+json") - .send() - .await? - .text() - .await?; - - serde_json::from_str(&response) - .map_err(|_| anyhow!("Failed to get upstream nightly version")) -} pub async fn get_local_nightly(config: &Config) -> Result { let downloads_dir = directories::get_downloads_directory(config).await?; @@ -50,24 +18,6 @@ pub async fn get_local_nightly(config: &Config) -> Result { } } -pub async fn get_commits_for_nightly( - client: &Client, - since: &DateTime, - until: &DateTime, -) -> Result> { - let response = client - .get(format!( - "https://api.github.com/repos/neovim/neovim/commits?since={since}&until={until}&per_page=100")) - .header("user-agent", "bob") - .header("Accept", "application/vnd.github.v3+json") - .send() - .await? - .text() - .await?; - - Ok(serde_json::from_str(&response)?) -} - pub async fn produce_nightly_vec(config: &Config) -> Result> { let downloads_dir = directories::get_downloads_directory(config).await?; let mut paths = fs::read_dir(&downloads_dir).await?; diff --git a/src/helpers/version/types.rs b/src/helpers/version/types.rs index 6ca5207..ffdb8df 100644 --- a/src/helpers/version/types.rs +++ b/src/helpers/version/types.rs @@ -1,7 +1,5 @@ -use chrono::{DateTime, Utc}; - use std::path::PathBuf; -use serde::{Deserialize, Serialize}; +use crate::github_requests::UpstreamVersion; pub struct ParsedVersion { pub tag_name: String, @@ -18,13 +16,6 @@ pub enum VersionType { NightlyRollback } -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct UpstreamVersion { - pub tag_name: String, - pub target_commitish: Option, - pub published_at: DateTime, -} - #[derive(Debug, Clone)] pub struct LocalNightly { pub data: UpstreamVersion, diff --git a/src/main.rs b/src/main.rs index 4625cd0..6144beb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ mod cli; mod config; mod handlers; mod helpers; +pub mod github_requests; extern crate core;