-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5c0cc69
commit b02971d
Showing
13 changed files
with
733 additions
and
577 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
fn main() { | ||
// Make TARGET environment variable available to code at build-time | ||
println!( | ||
"cargo:rustc-env=TARGET={}", | ||
std::env::var("TARGET").unwrap() | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
use bytes::Bytes; | ||
use color_eyre::{eyre::eyre, Result}; | ||
use futures_core::Stream; | ||
use futures_util::StreamExt; | ||
use std::path::Path; | ||
use tokio::{fs::File, io::AsyncWriteExt}; | ||
|
||
/// Get tag name of latest GitHub release | ||
pub async fn get_latest_version() -> Result<String> { | ||
Ok(octocrab::instance() | ||
.repos("cloudtruth", "cloudtruth-cli") | ||
.releases() | ||
.get_latest() | ||
.await? | ||
.tag_name) | ||
} | ||
|
||
/// Download asset from GitHub | ||
async fn get_release_asset( | ||
version: &str, | ||
asset_name: &str, | ||
) -> Result<impl Stream<Item = reqwest::Result<Bytes>>> { | ||
let github = octocrab::instance(); | ||
let download_url = github | ||
.repos("cloudtruth", "cloudtruth-cli") | ||
.releases() | ||
.get_by_tag(version) | ||
.await? | ||
.assets | ||
.into_iter() | ||
.find(|asset| asset.name == asset_name) | ||
.map(|asset| asset.browser_download_url) | ||
.ok_or_else(|| eyre!("Could not find release asset {asset_name} in release {version}"))?; | ||
Ok(reqwest::get(download_url).await?.bytes_stream()) | ||
} | ||
|
||
pub async fn download_release_asset( | ||
version: &str, | ||
asset_name: &str, | ||
download_path: &Path, | ||
) -> Result<()> { | ||
let mut f = File::create(download_path).await?; | ||
let mut stream = get_release_asset(version, asset_name).await?; | ||
while let Some(chunk) = stream.next().await { | ||
f.write_all(&chunk?).await?; | ||
} | ||
Ok(()) | ||
} | ||
|
||
// Get package name for the current build target, version, and file extension | ||
pub fn asset_name(version: &str, ext: &str) -> String { | ||
const TARGET: &str = env!("TARGET"); | ||
format!("cloudtruth-{version}-{TARGET}.{ext}") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,65 +1,43 @@ | ||
use crate::InstallError; | ||
use std::io; | ||
use std::io::Write; | ||
#[cfg(not(target_os = "windows"))] | ||
#[rustfmt::skip] | ||
use { | ||
crate::version::binary_version, | ||
std::fs, | ||
std::process::Command, | ||
std::str, | ||
tempfile::tempdir, | ||
}; | ||
use crate::{cli::InstallCommand, github, package_manager::choose_package_manager}; | ||
|
||
#[cfg(target_os = "windows")] | ||
pub fn install_latest_version(quiet: bool) -> Result<(), InstallError> { | ||
let text = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../../install.ps1")); | ||
let result = powershell_script::run(text); | ||
match result { | ||
Ok(output) => { | ||
if !quiet { | ||
if let Some(stdout_str) = output.stdout() { | ||
io::stdout().write_all(stdout_str.as_bytes())?; | ||
} | ||
} | ||
Ok(()) | ||
} | ||
Err(err) => Err(InstallError::InstallFailed(err.to_string())), | ||
} | ||
} | ||
|
||
#[cfg(not(target_os = "windows"))] | ||
pub fn install_latest_version(quiet: bool) -> Result<(), InstallError> { | ||
let filename = format!("cloudtruth-cli-install-{}.sh", binary_version()); | ||
let tempdir = tempdir()?; | ||
let fullpath = tempdir.path().join(filename); | ||
let fullname = fullpath.to_str().unwrap(); | ||
let text = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../../install.sh")); | ||
use color_eyre::Result; | ||
use flate2::read::GzDecoder; | ||
use std::{fs::File, path::Path}; | ||
use tar::Archive; | ||
use tempfile::tempdir; | ||
|
||
// write the install script to a file to a temporary directory | ||
fs::write(fullname, text)?; | ||
|
||
// attempt the chmod, and hope for success -- ignore failure | ||
let _ = Command::new("chmod").arg("a+x").arg(fullname).output(); | ||
pub fn unpack_tar_gz(src_file_path: &Path, dest_file_path: &Path) -> Result<()> { | ||
let tar_gz = File::open(src_file_path)?; | ||
let tar = GzDecoder::new(tar_gz); | ||
let mut archive = Archive::new(tar); | ||
archive.unpack(dest_file_path)?; | ||
Ok(()) | ||
} | ||
|
||
// now, actually run the installation script | ||
let result = Command::new(fullname).output(); | ||
match result { | ||
Ok(output) => match output.status.success() { | ||
true => { | ||
if !quiet { | ||
io::stdout().write_all(&output.stdout)?; | ||
} | ||
Ok(()) | ||
} | ||
false => { | ||
if !quiet { | ||
io::stdout().write_all(&output.stdout)?; | ||
} | ||
let stderr = str::from_utf8(&output.stderr)?; | ||
Err(InstallError::InstallFailed(stderr.to_string())) | ||
} | ||
}, | ||
Err(err) => Err(InstallError::FailedToRunInstall(err.to_string())), | ||
} | ||
pub async fn install(cmd: InstallCommand) -> Result<()> { | ||
let pkg_manager = choose_package_manager(); | ||
let version = match cmd.version { | ||
Some(version) => version, | ||
None => github::get_latest_version().await?, | ||
}; | ||
let tmp_dir = tempdir()?; | ||
let ext = if let Some(pkg_manager) = &pkg_manager { | ||
pkg_manager.package_ext() | ||
} else if cfg!(target_os = "windows") { | ||
"zip" | ||
} else { | ||
"tar.gz" | ||
}; | ||
let asset_name = github::asset_name(&version, ext); | ||
let download_path = tmp_dir.path().join(&asset_name); | ||
github::download_release_asset(&version, &asset_name, &download_path).await?; | ||
if let Some(pkg_manager) = pkg_manager { | ||
pkg_manager.install(&download_path)? | ||
} else if cfg!(target_os = "windows") { | ||
todo!() | ||
} else { | ||
unpack_tar_gz(&download_path, tmp_dir.path())?; | ||
println!("{:?}", tmp_dir.path()); | ||
}; | ||
Ok(()) | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,22 @@ | ||
pub mod cli; | ||
pub mod install; | ||
pub mod install_errors; | ||
pub mod package_manager; | ||
pub mod version; | ||
mod cli; | ||
mod github; | ||
mod install; | ||
mod package_manager; | ||
|
||
pub use cli::Cli; | ||
pub use install::install_latest_version; | ||
pub use install_errors::InstallError; | ||
pub use package_manager::find_package_managers; | ||
pub use version::{binary_version, get_latest_version}; | ||
use cli::Subcommand; | ||
use color_eyre::Result; | ||
use install::install; | ||
|
||
macro_rules! verbose { | ||
($($expr:tt)*) => { if $crate::cli::verbose() { println!($($expr)*)}} | ||
} | ||
pub(crate) use verbose; | ||
|
||
pub async fn cloudtruth_installer_cli() -> Result<()> { | ||
let cli = cli::parse(); | ||
#[allow(irrefutable_let_patterns)] | ||
if let Subcommand::Install(install_cmd) = cli.command { | ||
install(install_cmd).await?; | ||
} | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,8 @@ | ||
use cloudtruth_installer::{cli, find_package_managers, package_manager::PackageManagerBin}; | ||
use cloudtruth_installer::cloudtruth_installer_cli; | ||
|
||
pub fn main() -> color_eyre::Result<()> { | ||
#[tokio::main] | ||
pub async fn main() -> color_eyre::Result<()> { | ||
color_eyre::install()?; | ||
cli::parse(); | ||
let pkg_manager = if !cli::interactive() { | ||
// When running non-interactive, take first available package manager | ||
find_package_managers().next().unwrap() | ||
} else { | ||
let mut pkg_managers: Vec<PackageManagerBin> = find_package_managers().collect(); | ||
if pkg_managers.len() == 1 { | ||
pkg_managers.swap_remove(0) | ||
} else { | ||
// Prompt user for package manager choice | ||
todo!() | ||
} | ||
}; | ||
println!("{}", pkg_manager); | ||
cloudtruth_installer_cli().await?; | ||
Ok(()) | ||
} |
Oops, something went wrong.