Skip to content

Commit

Permalink
Merge pull request #4 from WeareJH/auto
Browse files Browse the repository at this point in the history
adding updater
  • Loading branch information
shakyShane authored Mar 15, 2020
2 parents fac507b + 037ccb2 commit cf2ed04
Show file tree
Hide file tree
Showing 6 changed files with 280 additions and 2 deletions.
79 changes: 79 additions & 0 deletions express-install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/bin/bash
#set -x #uncomment for debug mode

clear_term() {
#comment out for output
clear
#echo "debug -- clear"
}

aborting_install() {
clear_term
echo "Aborting Install"
}

path_check() {
path_check_var=$(which jhira)
if [ -x "$path_check_var" ] ; then
echo "JHIRA appears to be in your path! Continuing..."
sleep 2
else
echo "JHIRA does not appear to be in your path,"
echo "Would you like the installer to try to auto add JHIRA to your path? (y/n) "
read addToPath
if [[ $addToPath == "y" ]] ; then
touch ~/.zshrc
echo "export PATH=\"$PATH:/opt\"" >> ~/.zshrc
echo "Now we are going to refresh your terminal"
sleep 2
source ~/.zshrc
else
echo "Skipping add to path step"
fi
fi
}

exec_install() {
clear_term
echo "Beginning express download of JHIRA"
curl -L "https://github.com/wearejh/jhira/releases/download/v0.1.2/jhira" --output jhira-temp-binary-file
chmod +x ./jhira-temp-binary-file
echo "Download successful!"
echo "You may now be asked for your password to install the JHIRA binary"
sudo mkdir -p /opt
sudo chown -R $(whoami) /opt
mv ./jhira-temp-binary-file /opt/jhira
path_check
echo "Now the self-update function will run to get the latest version!"
sleep 2
jhira self-update
echo "Thank you for using the express installer!"
echo "(You may need to run \"source ~/.zshrc\" - without the quotes - to see jhira)"
}

clear_term
echo "Welcome to the JHIRA Express installer!"
echo "Would you like to install JHIRA? (y/n) "
read continueInstall
if [[ $continueInstall == "y" ]] ; then
echo "Ok, installing now"
path_to_executable=$(which jhira)
if [ -x "$path_to_executable" ] ; then
clear_term
echo "Looks like jhira is already installed"
echo "Would you like to reinstall?"
echo " - this will delete your existing installation (y/n) "
read reinstall
if [[ $reinstall == "y" ]] ; then
rm $(which jhira)
exec_install
else
aborting_install
fi
else
exec_install
fi
else
aborting_install
fi

2 changes: 1 addition & 1 deletion jhira_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ argh = "0.1.3"
failure = "0.1.6"
structopt = "0.3.9"
chrono = "0.4.10"
reqwest = { version = "0.10.3", features = ["json"] }
reqwest = { version = "0.10.3", features = ["json", "blocking"] }
serde = "1.0.104"
serde_json = "1.0.48"
serde_derive = "1.0.104"
Expand Down
12 changes: 12 additions & 0 deletions jhira_core/src/jhira.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use std::sync::Arc;

use crate::epic::EpicCmd;
use crate::jql::JqlCmd;
use crate::self_update;

#[derive(Debug)]
pub struct Jhira {
Expand Down Expand Up @@ -61,6 +62,13 @@ pub enum Subcommands {
#[structopt(subcommand)]
cmd: Worklog,
},
/// Update to the latest version
#[structopt(name = "self-update", alias = "update")]
SelfUpdate {
/// Accept all prompts and update automatically
#[structopt(long = "yes", short = "y")]
yes: bool,
},
}

#[derive(Debug, Fail)]
Expand Down Expand Up @@ -106,6 +114,10 @@ impl Jhira {
let auth = Auth { api, domain, email };
auth.login()
}
SelfUpdate { yes } => {
let self_update = self_update::SelfUpdate { yes };
self_update.into()
}
}?;
Ok((opt2, upcoming))
}
Expand Down
1 change: 1 addition & 0 deletions jhira_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub mod issues;
pub mod jhira;
pub mod jql;
pub mod login;
pub mod self_update;
pub mod task;
pub mod worklog;

Expand Down
186 changes: 186 additions & 0 deletions jhira_core/src/self_update/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
use crate::async_task::{AsyncTask, Return, TaskOutput};
use crate::task::TaskSequence;
use ansi_term::Colour::{Blue, Green, Red};
use async_trait::async_trait;
use std::fs::File;
use std::process::Command;
use std::{env, io};

#[derive(Debug, Clone)]
pub struct SelfUpdate {
pub yes: bool,
}

impl From<SelfUpdate> for TaskSequence {
fn from(self_update: SelfUpdate) -> Self {
Ok(vec![Box::new(self_update)])
}
}

#[async_trait(?Send)]
impl AsyncTask for SelfUpdate {
async fn exec(&self) -> Return {
let _output = run_self_update(self.yes).await?;
Ok(TaskOutput::Done)
}
}

#[derive(Debug, Fail)]
enum SelfUpdateError {
#[fail(display = "Cannot read path to executable")]
PermissionDenied,
#[fail(display = "Assets contained no items")]
NoItems,
}

#[derive(Serialize, Deserialize, Debug)]
struct JhiraJson {
assets: Vec<JhiraJsonAsset>,
name: String,
tag_name: String,
}

#[derive(Serialize, Deserialize, Debug)]
struct JhiraJsonAsset {
browser_download_url: String,
size: i32,
name: String,
}

pub async fn run_self_update(is_auto_confirmed: bool) -> Result<(), failure::Error> {
let request_url = String::from("https://api.github.com/repos/wearejh/jhira/releases/latest");
let response = reqwest::get(&request_url).await?;
let resp = response.text().await?;

let jhira_path_cmd = env::current_exe()?;

let jhira_path = jhira_path_cmd
.to_str()
.ok_or(SelfUpdateError::PermissionDenied)?;

let jhira: JhiraJson = serde_json::from_str(&resp)?;
let url = jhira
.assets
.get(0)
.map(|asset| asset.browser_download_url.clone())
.ok_or(SelfUpdateError::NoItems)?;

let name = jhira
.assets
.get(0)
.map(|asset| asset.name.clone())
.ok_or(SelfUpdateError::NoItems)?;

let size = jhira
.assets
.get(0)
.map(|asset| asset.size)
.ok_or(SelfUpdateError::NoItems)?;

clear_terminal(is_auto_confirmed);
let mut ok_to_proceed: bool = false;
if !is_auto_confirmed {
println!("{}", Green.paint("=====[Jhira Self Updater]====="));
println!();
println!("File name : {}", name);
println!("Description : {}", jhira.name);
println!("Url : {}", url);
println!("Version : {}", jhira.tag_name);
println!("Size : {}kb", size / 1024);
println!();
println!(
"Current jhira directory is reported as: {}",
Blue.paint(jhira_path)
);
println!();
if jhira_path != "/opt/jhira" {
println!(
"{}",
Red.paint("Warning! Working directory is NOT the standard directory expected.")
);
println!("{}", Red.paint("Expected directory to be /opt/jhira"));
println!(
"{}",
Red.paint("You can proceed with the update, but at your own risk!")
);
println!();
println!(
"{} {} {}",
Blue.paint("If you wish to fix this, exit out of this app and run 'sudo mv"),
Blue.paint(jhira_path),
Blue.paint("/opt/jhira'")
);
println!(
"{}",
Blue.paint("More info here: https://github.com/WeareJH/jhira#manual")
);
} else {
println!("{}", Green.paint("Working directory is ok!"));
}
println!();

loop {
println!("Ok to proceed? (y/n)");
let mut user_input = String::new();

io::stdin()
.read_line(&mut user_input)
.expect("Failed to read line");

if let Some('\n') = user_input.chars().next_back() {
user_input.pop();
}
if let Some('\r') = user_input.chars().next_back() {
user_input.pop();
}
if user_input == "y" || user_input == "yes" {
ok_to_proceed = true;
break;
} else if user_input == "n" || user_input == "no" {
break;
} else {
clear_terminal(is_auto_confirmed);
println!("Unrecognised input: '{}'", user_input);
}
}
} else {
println!("Auto confirm flag passed, continuing...");
ok_to_proceed = true;
}

if ok_to_proceed {
clear_terminal(is_auto_confirmed);
println!("Starting update...");

let mut response = reqwest::blocking::get("https://www.rust-lang.org/")?;

let current_path = std::path::PathBuf::from(jhira_path);
let mut current_dir = File::create(current_path)?;

println!("Attempting to copy to {}", jhira_path);

response.copy_to(&mut current_dir)?;

clear_terminal(is_auto_confirmed);
let version = Command::new(jhira_path)
.arg("-V")
.output()
.expect("failed to execute process");
println!("Success!");
println!(
"You updated to {}",
std::str::from_utf8(&version.stdout).unwrap()
);
} else {
clear_terminal(is_auto_confirmed);
println!("Aborted update");
}

Ok(())
}

fn clear_terminal(is_auto_confirmed: bool) {
if !is_auto_confirmed {
print!("{}[2J", 27 as char);
}
}
2 changes: 1 addition & 1 deletion pre-push.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
set -eo pipefail
cargo fix --allow-dirty --allow-staged && cargo fmt
cargo fix --allow-dirty --allow-staged && cargo fmt --all
cargo clippy
cargo check
cargo test
Expand Down

0 comments on commit cf2ed04

Please sign in to comment.