Skip to content

Commit

Permalink
Added option to use github api or git
Browse files Browse the repository at this point in the history
  • Loading branch information
x0f5c3 committed Dec 30, 2020
1 parent 0a590aa commit bad74b9
Show file tree
Hide file tree
Showing 12 changed files with 192 additions and 40 deletions.
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions .idea/go_version_manager.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
24 changes: 24 additions & 0 deletions src/consts.rs
Original file line number Diff line number Diff line change
@@ -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";
16 changes: 16 additions & 0 deletions src/github.rs
Original file line number Diff line number Diff line change
@@ -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,
}
112 changes: 79 additions & 33 deletions src/goversion.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -29,16 +23,38 @@ pub struct GoVersion {
impl GoVersion {
/// Gets golang versions from git tags
fn get_git_versions() -> Result<Vec<String>, Error> {
let output: Vec<String> = 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<String> =
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<Vec<Versioning>, Error> {
let client = reqwest::Client::new();
let resp: Vec<Tag> = 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<Versioning> = 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::<Vec<_>>();
filtered.sort_unstable();
filtered.reverse();
Ok(filtered)
}
/// Parses the versions into Versioning structs
pub fn get_versions() -> Result<Vec<Versioning>, Error> {
let unparsed = Self::get_git_versions()?;
Expand All @@ -52,8 +68,12 @@ impl GoVersion {
Ok(parsed)
}
/// Gets the latest versions by sorting the parsed versions
fn get_latest() -> Result<Versioning, Error> {
let mut versions = GoVersion::get_versions()?;
async fn get_latest(git: bool) -> Result<Versioning, Error> {
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)
Expand All @@ -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
Expand All @@ -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<PathBuf, Error> {
Expand All @@ -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<Self, Error> {
let vers = GoVersion::get_latest()?;
pub async fn latest(git: bool) -> Result<Self, Error> {
let vers = GoVersion::get_latest(git).await?;
let url = GoVersion::construct_url(&vers);
let sha = GoVersion::get_sha(&vers).await?;
Ok(GoVersion {
Expand All @@ -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,
},
}
}
21 changes: 15 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ struct Opt {
version: Option<Versioning>,
#[structopt(short, long)]
interactive: bool,
#[structopt(short, long)]
git: bool,
}

/// Reads output path from command line arguments
Expand All @@ -31,22 +33,28 @@ 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?
} else if opt.interactive && git_present {
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?
}
}
};
Expand All @@ -69,7 +77,6 @@ async fn main() -> Result<(), Error> {
None,
None,
);

Ok(())
}

Expand All @@ -96,5 +103,7 @@ fn ask_for_version(term: &Term) -> Result<Versioning, Error> {
}
}

mod consts;
mod error;
mod github;
mod goversion;

0 comments on commit bad74b9

Please sign in to comment.