Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
# Conflicts:
#	Cargo.lock
#	src/commands/install.rs
#	src/commands/update.rs
#	src/error.rs
  • Loading branch information
x0f5c3 committed Dec 3, 2021
2 parents ca6ca2b + e4c65cb commit ac80c68
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 91 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@ features = ["progress", "json", "threaded"]
[target.'cfg(windows)'.dependencies]
zip = "*"
zip-extensions = "*"
self_update = { version = "0.27.0", default-features = false, features = ["rustls", "archive-zip", "compression-zip-deflate"] }

[target.'cfg(not(windows))'.dependencies]
flate2 = "1.0.22"
tar = "*"
self_update = { version = "0.27.0", default-features = false, features = ["rustls", "archive-tar", "compression-flate2"] }

[badges]
github = { repository = "x0f5c3/go_version_manager" }
5 changes: 2 additions & 3 deletions src/commands/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,12 @@ impl Install {
let res = golang.download(None, workers)?;
res.unpack(&c.install_path)?;
let bin_path = &c.install_path.join("bin");
let path_check = check_in_path(bin_path)?;
if !path_check {
if !check_in_path(bin_path)? {
paris::info!("Directory {} not in PATH", bin_path.display());
}
Ok(())
} else {
Err(Error::PathBufErr)
Err(Error::NOPerm)
}
}
}
44 changes: 16 additions & 28 deletions src/commands/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use structopt::StructOpt;

use crate::commands::utils::check_writable;
use crate::config::Config;
use crate::consts::{CONFIG_PATH, DEFAULT_INSTALL};
use crate::consts::{CONFIG_PATH, CURRENT_INSTALL, DEFAULT_INSTALL};
use crate::error::Error;
use crate::goversion::GoVersions;
use crate::Result;
Expand All @@ -24,36 +24,24 @@ impl Update {
pub(crate) fn run(self) -> Result<()> {
let workers = self.workers.unwrap_or(num_cpus::get() as u8);
let config_path = self.config_path.unwrap_or_else(|| CONFIG_PATH.clone());
let install_path = self.install_path.unwrap_or_else(|| DEFAULT_INSTALL.clone());
let c = Config::new(install_path, config_path)?;
let install_path = self
.install_path
.or_else(|| CURRENT_INSTALL.clone())
.unwrap_or_else(|| DEFAULT_INSTALL.clone());
let c = Config::new(install_path.clone(), config_path)?;
let latest = GoVersions::download_latest()?;
let res = {
if let Some(v) = c.current {
if v.version == latest.version {
paris::success!("You already have the latest version {}", v.version);
quit::with_code(0);
} else {
let res = std::fs::metadata(&c.install_path);
if let Err(e) = res {
if let std::io::ErrorKind::PermissionDenied = e.kind() {
paris::error!(
"You don't have privs to install in {}",
c.install_path.display()
);
quit::with_code(127);
} else {
Err(e.into())
}
} else {
latest.download(None, workers)
}
}
} else if check_writable(c.install_path.parent().ok_or(Error::PathBufErr)?)? {
let res = latest.check_newer(&c.install_path).and_then(|x| {
if x {
latest.download(None, workers)
} else {
Err(Error::PathBufErr)
paris::success!("You already have the latest version");
quit::with_code(0);
}
};
res?.unpack(&c.install_path)
});
if check_writable(c.install_path.parent().ok_or(Error::PathBufErr)?)? {
res?.unpack(&install_path)
} else {
Err(Error::NOPerm)
}
}
}
3 changes: 2 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::consts::VERSION_LIST;
use crate::goversion::{get_local_version, GoVersion};
use crate::goversion::GoVersion;
use crate::utils::get_local_version;
use crate::{Error, GoVersions, Result};
use serde::{Deserialize, Serialize};
use std::fs;
Expand Down
2 changes: 1 addition & 1 deletion src/decompressor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ impl<R: Read + Seek + BufRead> ToDecompress<R> {
pub(crate) fn extract(&mut self, path: &Path) -> Result<()> {
self.decompressor
.unpack(path.parent().ok_or(Error::PathBufErr)?)
.map_err(Error::IOError)
.map_err(Error::IOErr)
}
}
4 changes: 3 additions & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Error)]
pub enum Error {
#[error("IOError")]
IOError(#[from] std::io::Error),
IOErr(#[from] std::io::Error),
#[error("Manic error: {0}")]
ManicErr(#[from] manic::ManicError),
#[error("Failed to convert Pathbuf to str")]
Expand All @@ -28,6 +28,8 @@ pub enum Error {
VARErr(#[from] VarError),
#[error("Permission denied, restart the program as root")]
NOPerm,
#[error("Update failed {0}")]
UpdateErr(#[from] self_update::errors::Error),
#[error("Regex error: {0}")]
RegexErr(#[from] regex::Error),
}
57 changes: 11 additions & 46 deletions src/goversion.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::consts::{DEFAULT_INSTALL, DL_PAGE, DL_URL, FILE_EXT, GIT_VERSIONS, VERSION_LIST};
use crate::consts::{DL_PAGE, DL_URL, FILE_EXT, GIT_VERSIONS, VERSION_LIST};
use crate::decompressor::ToDecompress;
use crate::error::Error;
use crate::error::Result;
use duct::cmd;
use crate::utils::get_local_version;
use git2::{Direction, Remote};
use manic::Downloader;
use rayon::prelude::*;
Expand Down Expand Up @@ -93,23 +93,7 @@ impl GoVersions {
pub fn latest(&self) -> GoVersion {
self.latest.clone()
}
pub fn check_local_latest(&self, path: Option<PathBuf>) -> Result<bool> {
let local_vers = if let Some(p) = path {
get_local_version(&p)?
} else {
get_local_version(&DEFAULT_INSTALL)?
};
if local_vers.is_none() {
return Ok(false);
}
let somed = local_vers.unwrap();
let latest = self.latest().version;
if somed == latest {
Ok(true)
} else {
Ok(false)
}
}

/// Gets golang versions from git tags
pub fn raw_git_versions() -> Result<Vec<String>> {
let mut remote = Remote::create_detached("https://github.com/golang/go")?;
Expand Down Expand Up @@ -254,34 +238,15 @@ impl GoVersion {
})
}
}
}

pub fn check_git() -> bool {
match cmd!("git", "version").stdout_null().run() {
Ok(_) => true,
Err(e) => !matches!(e.kind(), std::io::ErrorKind::NotFound),
}
}

pub fn get_local_version(path: &Path) -> Result<Option<SemVer>> {
let output = cmd!(
path.join("bin/go").to_str().ok_or(Error::PathBufErr)?,
"version"
)
.read();
if let Err(e) = output {
return if e.kind() == std::io::ErrorKind::NotFound {
Ok(None)
pub(crate) fn check_newer(&self, path: &Path) -> Result<bool> {
if let Some(s) = get_local_version(path)? {
if s < self.version {
Ok(true)
} else {
Ok(false)
}
} else {
Err(e.into())
};
} else if let Ok(vers) = output {
let version = vers.split(' ').nth(2);
if version.is_none() {
return Ok(None);
Ok(true)
}
let somed = version.unwrap().replace("go", "");
return Ok(SemVer::new(somed.as_ref()));
}
Ok(None)
}
17 changes: 12 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#![allow(dead_code, clippy::enum_variant_names)]
//! `go_version_manager` is a small program intended to download the latest or chosen golang version
//! from the official site also checking the checksum for the file
#[macro_use]
extern crate lazy_static;

use std::path::PathBuf;
use human_panic::setup_panic;

use error::Error;
Expand All @@ -14,6 +14,7 @@ use crate::consts::FILE_EXT;
use crate::error::Result;
use crate::goversion::Downloaded;
use crate::goversion::GoVersions;
use crate::utils::check_self_update;

/// Reads output path from command line arguments
/// and downloads latest golang version to it
Expand All @@ -25,10 +26,12 @@ fn main(opt: Command) -> Result<()> {
setup_panic!();
init_consts();
pretty_env_logger::init();
let res = opt.run();
if let Err(e) = res {
paris::error!("Error: {}", e);
}
// let res = opt.run();
// if let Err(e) = res {
// paris::error!("Error: {}", e);
// }
let up = check_self_update()?;
println!("{:?}", up);
#[cfg(debug_assertions)]
paris::info!("Execution time: {}s", now.elapsed().as_secs_f64());
Ok(())
Expand All @@ -42,3 +45,7 @@ mod error;
mod goversion;
mod installed;
mod utils;

pub fn path_test() -> Result<Option<PathBuf>> {
utils::get_local_path()
}
82 changes: 76 additions & 6 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,39 @@
use std::fmt::Debug;
use crate::consts::{CONFIG_DIR, CONFIG_PATH, CURRENT_INSTALL, DEFAULT_INSTALL, VERSION_LIST};
use crate::Error;
use crate::Result;
use crate::{GoVersions, FILE_EXT};
use console::Term;
use dialoguer::theme::ColorfulTheme;
use dialoguer::Select;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use versions::SemVer;
use self_update::backends::github::Update;
use self_update::cargo_crate_version;
use self_update::update::ReleaseUpdate;

pub(crate) fn get_local_path() -> Option<PathBuf> {
pub(crate) fn get_local_path() -> Result<Option<PathBuf>> {
let cmd = if cfg!(windows) {
"Get-Command"
"(Get-Command go).Path"
} else {
"which"
};
duct::cmd!(cmd, "go")
.read()
.into_iter()
.filter_map(|x| {
.map(|x| {
PathBuf::from(x)
.parent()
.into_iter()
.filter_map(|x| x.parent())
.next()
.map(|x| x.to_path_buf())
})
.next()
.or_else(|x| {
if x.kind() == std::io::ErrorKind::NotFound {
return Ok(None);
}
Err(x.into())
})
}

pub(crate) fn init_consts() {
Expand Down Expand Up @@ -54,3 +63,64 @@ pub(crate) fn ask_for_version(term: &Term, versions: &GoVersions) -> Result<SemV
quit::with_code(127);
}
}

pub(crate) fn get_local_version(path: &Path) -> Result<Option<SemVer>> {
duct::cmd!(
path.join("bin/go").to_str().ok_or(Error::PathBufErr)?,
"version"
)
.read()
.map(|x| {
x.split(' ')
.nth(2)
.and_then(|x| SemVer::new(&x.replace("go", "")))
})
.or_else(|x| {
if x.kind() == std::io::ErrorKind::NotFound {
return Ok(None);
}
Err(x.into())
})
}

enum ShouldUpdate {
Yes(Box<dyn ReleaseUpdate>),
No,
}

impl ShouldUpdate {
fn new(update: Option<Box<dyn ReleaseUpdate>>) -> Self {
if let Some(up) = update {
Self::Yes(up)
} else {
Self::No
}
}
}

pub(crate) fn check_self_update() -> Result<ShouldUpdate> {
let up = Update::configure()
.repo_owner("x0f5c3")
.repo_name("go_version_manager")
.current_version(cargo_crate_version!())
.build()?;
let rel = up.get_latest_release()?;
if self_update::version::bump_is_greater(&up.current_version(), &rel.version)? {
Ok(ShouldUpdate::new(Some(up.into())))
} else {
Ok(ShouldUpdate::No)
}
}

pub(crate) fn self_update() -> Result<()> {
let status = Update::configure()
.repo_owner("x0f5c3")
.repo_name("go_version_manager")
.current_version(cargo_crate_version!())
.build()?
.update()?;
if status.updated() {
paris::success!("Updated the binary to version {}", status.version());
}
Ok(())
}

0 comments on commit ac80c68

Please sign in to comment.