diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..73f69e0
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/go_version_manager.iml b/.idea/go_version_manager.iml
new file mode 100644
index 0000000..c254557
--- /dev/null
+++ b/.idea/go_version_manager.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..146ab09
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..28a804d
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..a28843a
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
index adeae9d..ce1d6ce 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -411,10 +411,12 @@ dependencies = [
"duct",
"human-panic",
"indicatif",
+ "lazy_static",
"leg",
"manic",
"quit",
"reqwest",
+ "serde",
"soup",
"structopt",
"thiserror",
@@ -1309,6 +1311,7 @@ dependencies = [
"pin-project-lite 0.2.0",
"rustls",
"serde",
+ "serde_json",
"serde_urlencoded",
"tokio",
"tokio-rustls",
@@ -1375,6 +1378,9 @@ name = "serde"
version = "1.0.116"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5"
+dependencies = [
+ "serde_derive",
+]
[[package]]
name = "serde_derive"
diff --git a/Cargo.toml b/Cargo.toml
index d130a2a..504d392 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -28,11 +28,13 @@ dialoguer = "0.7.1"
quit = "1.1.2"
duct = "*"
leg = "0.4.1"
+lazy_static = "*"
+serde = { version = "*", features = ["derive"] }
colored = "^1.8.0"
[dependencies.reqwest]
version = "0.10.10"
default-features = false
-features = ["rustls-tls"]
+features = ["rustls-tls", "json"]
[badges]
diff --git a/src/consts.rs b/src/consts.rs
new file mode 100644
index 0000000..692b3e6
--- /dev/null
+++ b/src/consts.rs
@@ -0,0 +1,24 @@
+#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
+pub const FILE_EXT: &str = "linux-amd64.tar.gz";
+#[cfg(all(target_os = "linux", target_arch = "x86"))]
+pub const FILE_EXT: &str = "linux-386.tar.gz";
+#[cfg(all(target_os = "linux", target_arch = "aarch64"))]
+pub const FILE_EXT: &str = "linux-arm64.tar.gz";
+#[cfg(all(target_os = "linux", target_arch = "arm"))]
+pub const FILE_EXT: &str = "linux-armv6l.tar.gz";
+#[cfg(all(target_os = "linux", target_arch = "powerpc64"))]
+pub const FILE_EXT: &str = "linux-ppc64le.tar.gz";
+#[cfg(all(target_os = "linux", target_arch = "s390x"))]
+pub const FILE_EXT: &str = "linux-s390x.tar.gz";
+#[cfg(all(target_os = "windows", target_arch = "x86_64"))]
+pub const FILE_EXT: &str = "windows-amd64.msi";
+#[cfg(all(target_os = "windows", target_arch = "x86"))]
+pub const FILE_EXT: &str = "windows-386.msi";
+#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
+pub const FILE_EXT: &str = "darwin-amd64.pkg";
+#[cfg(all(target_os = "freebsd", target_arch = "x86_64"))]
+pub const FILE_EXT: &str = "freebsd-amd64.tar.gz";
+#[cfg(all(target_os = "freebsd", target_arch = "x86"))]
+pub const FILE_EXT: &str = "freebsd-386.tar.gz";
+
+pub const DL_URL: &str = "https://golang.org/dl";
diff --git a/src/github.rs b/src/github.rs
new file mode 100644
index 0000000..f5cc333
--- /dev/null
+++ b/src/github.rs
@@ -0,0 +1,16 @@
+use serde::{Deserialize, Serialize};
+
+#[derive(Debug, Deserialize, Serialize)]
+pub struct Tag {
+ pub name: String,
+ zipball_url: String,
+ tarball_url: String,
+ commit: Commit,
+ node_id: String,
+}
+
+#[derive(Debug, Deserialize, Serialize)]
+pub struct Commit {
+ sha: String,
+ url: String,
+}
diff --git a/src/goversion.rs b/src/goversion.rs
index a74bc97..3ed020a 100644
--- a/src/goversion.rs
+++ b/src/goversion.rs
@@ -1,20 +1,14 @@
-
+use crate::consts::{DL_URL, FILE_EXT};
+use crate::error::Error;
+use crate::github::Tag;
+use duct::cmd;
use indicatif::ProgressBar;
+use manic::progress::downloader;
+use reqwest::header::USER_AGENT;
use soup::prelude::*;
use soup::Soup;
use std::path::PathBuf;
use versions::Versioning;
-use crate::error::Error;
-use manic::progress::downloader;
-use duct::cmd;
-#[cfg(target_os = "linux")]
-static FILE_EXT: &str = "linux-amd64.tar.gz";
-#[cfg(target_os = "windows")]
-static FILE_EXT: &str = "windows-amd64.msi";
-#[cfg(target_os = "macos")]
-static FILE_EXT: &str = "darwin-amd64.pkg";
-
-static DL_URL: &str = "https://golang.org/dl";
/// Golang version represented as a struct
pub struct GoVersion {
@@ -29,16 +23,38 @@ pub struct GoVersion {
impl GoVersion {
/// Gets golang versions from git tags
fn get_git_versions() -> Result, Error> {
- let output: Vec = cmd!("git", "ls-remote", "--tags", "https://github.com/golang/go").read()?
- .trim()
- .lines()
- .filter(|x| x.contains("go"))
- .filter_map(|x| x.split('\t').nth(1))
- .filter_map(|x| x.split('/').nth(2))
- .map(|x| x.replace("go", ""))
- .collect();
+ let output: Vec =
+ cmd!("git", "ls-remote", "--tags", "https://github.com/golang/go")
+ .read()?
+ .trim()
+ .lines()
+ .filter(|x| x.contains("go"))
+ .filter_map(|x| x.split('\t').nth(1))
+ .filter_map(|x| x.split('/').nth(2))
+ .map(|x| x.replace("go", ""))
+ .collect();
Ok(output)
}
+ pub async fn get_gh_version() -> Result, Error> {
+ let client = reqwest::Client::new();
+ let resp: Vec = client
+ .get("https://api.github.com/repos/golang/go/tags?page=2&per_page=100")
+ .header(USER_AGENT, "Get_Tag")
+ .send()
+ .await?
+ .json()
+ .await?;
+ let mut filtered: Vec = resp
+ .iter()
+ .filter(|x| x.name.contains("go"))
+ .map(|x| x.name.clone().replace("go", ""))
+ .filter_map(|x| Versioning::new(x.as_ref()))
+ .filter(|x| x.is_ideal())
+ .collect::>();
+ filtered.sort_unstable();
+ filtered.reverse();
+ Ok(filtered)
+ }
/// Parses the versions into Versioning structs
pub fn get_versions() -> Result, Error> {
let unparsed = Self::get_git_versions()?;
@@ -52,8 +68,12 @@ impl GoVersion {
Ok(parsed)
}
/// Gets the latest versions by sorting the parsed versions
- fn get_latest() -> Result {
- let mut versions = GoVersion::get_versions()?;
+ async fn get_latest(git: bool) -> Result {
+ let mut versions = if git {
+ Self::get_versions()?
+ } else {
+ Self::get_gh_version().await?
+ };
versions.sort_by(|a, b| b.cmp(&a));
let latest = versions.first().ok_or(Error::NoVersion)?.to_owned();
Ok(latest)
@@ -64,8 +84,25 @@ impl GoVersion {
let soup = Soup::new(&resp.text().await?);
let govers = format!("go{}", vers);
let gofile = format!("{}.{}", govers, FILE_EXT);
- let latest = soup.tag("div").attr("id", govers).find().ok_or(Error::NoSha)?;
- let mut children = latest.tag("tr").class("highlight").find_all();
+ println!("{}", gofile);
+ let latest = soup
+ .tag("div")
+ .attr("id", govers)
+ .find()
+ .ok_or(Error::NoSha)?;
+ println!("Found latest");
+ let mut children = latest.tag("tr").find_all().filter(|f| {
+ let cls = f.get("class");
+ if cls.is_some() {
+ if cls.unwrap() == "first" {
+ false
+ } else {
+ true
+ }
+ } else {
+ true
+ }
+ });
let found = children
.find(|child| {
child
@@ -76,12 +113,13 @@ impl GoVersion {
.contains(&gofile)
})
.ok_or(Error::NoSha)?;
+ println!("Found filename");
let sha = found.tag("tt").find().ok_or(Error::NoSha)?.text();
Ok(sha)
}
/// Constructs the url for the version
fn construct_url(vers: impl std::fmt::Display) -> String {
- format!("{}/go{}.{}", DL_URL, vers, FILE_EXT)
+ return format!("{}/go{}.{}", DL_URL, vers, FILE_EXT);
}
/// Downloads the required version async
pub async fn download(&self, output: PathBuf, workers: u8) -> Result {
@@ -90,15 +128,23 @@ impl GoVersion {
.progress_chars("#>-");
let path_str = output.to_str().ok_or(Error::PathBufErr)?;
let pb = ProgressBar::new(100);
- pb.set_style(style);
+ pb.set_style(style);
let client = reqwest::Client::new();
let filename = manic::downloader::get_filename(&self.dl_url)?;
- downloader::download_verify_and_save(&client, &self.dl_url, workers, &self.sha256, path_str, pb).await?;
+ downloader::download_verify_and_save(
+ &client,
+ &self.dl_url,
+ workers,
+ &self.sha256,
+ path_str,
+ pb,
+ )
+ .await?;
Ok(output.join(filename))
}
/// Constructs the latest GoVersion
- pub async fn latest() -> Result {
- let vers = GoVersion::get_latest()?;
+ pub async fn latest(git: bool) -> Result {
+ let vers = GoVersion::get_latest(git).await?;
let url = GoVersion::construct_url(&vers);
let sha = GoVersion::get_sha(&vers).await?;
Ok(GoVersion {
@@ -120,10 +166,10 @@ impl GoVersion {
pub fn check_git() -> bool {
match cmd!("git", "version").stdout_null().run() {
- Ok(_) => return true,
+ Ok(_) => true,
Err(e) => match e.kind() {
- std::io::ErrorKind::NotFound => return false,
- _ => return true,
- }
+ std::io::ErrorKind::NotFound => false,
+ _ => true,
+ },
}
}
diff --git a/src/main.rs b/src/main.rs
index 44e0d0f..600399c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -20,6 +20,8 @@ struct Opt {
version: Option,
#[structopt(short, long)]
interactive: bool,
+ #[structopt(short, long)]
+ git: bool,
}
/// Reads output path from command line arguments
@@ -31,6 +33,8 @@ async fn main() -> Result<(), Error> {
let opt = Opt::from_args();
let term = Term::stdout();
let git_present = check_git();
+ println!("ARCH: {}", std::env::consts::ARCH);
+ println!("File ext: {}", crate::consts::FILE_EXT);
let golang = {
if let Some(vers) = opt.version {
goversion::GoVersion::version(vers).await?
@@ -38,15 +42,19 @@ async fn main() -> Result<(), Error> {
let vers = ask_for_version(&term)?;
goversion::GoVersion::version(vers).await?
} else {
- if git_present {
- goversion::GoVersion::latest().await?
- } else {
- leg::error(
+ if opt.git {
+ if git_present {
+ goversion::GoVersion::latest(true).await?
+ } else {
+ leg::error(
"You requested the latest version and git is not installed, please install git",
None,
None,
);
- quit::with_code(127);
+ quit::with_code(127);
+ }
+ } else {
+ goversion::GoVersion::latest(false).await?
}
}
};
@@ -69,7 +77,6 @@ async fn main() -> Result<(), Error> {
None,
None,
);
-
Ok(())
}
@@ -96,5 +103,7 @@ fn ask_for_version(term: &Term) -> Result {
}
}
+mod consts;
mod error;
+mod github;
mod goversion;