The modules and tests are no longer relevant since master has changed a lot since the code was split into smalled modules.master
parent
b15f062906
commit
714a8a1581
@ -1,44 +0,0 @@ |
|||||||
//! Code related to error handling for binary-install
|
|
||||||
|
|
||||||
/// Errors that can potentially occur in `binary-install`.
|
|
||||||
#[derive(Debug, Fail)] |
|
||||||
pub enum Error { |
|
||||||
#[fail(display = "{}", message)] |
|
||||||
/// An error related to an archive that we downloaded.
|
|
||||||
Archive { |
|
||||||
/// Error message.
|
|
||||||
message: String, |
|
||||||
}, |
|
||||||
|
|
||||||
#[fail(display = "{}", message)] |
|
||||||
/// Error related to some HTTP request.
|
|
||||||
Http { |
|
||||||
/// Error message.
|
|
||||||
message: String, |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
impl Error { |
|
||||||
/// Construct an archive error.
|
|
||||||
pub fn archive(message: &str) -> Self { |
|
||||||
Error::Archive { |
|
||||||
message: message.to_string(), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// Construct an http error.
|
|
||||||
pub fn http(message: &str) -> Self { |
|
||||||
Error::Http { |
|
||||||
message: message.to_string(), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// Get a string description of this error's type.
|
|
||||||
pub fn error_type(&self) -> String { |
|
||||||
match self { |
|
||||||
Error::Archive { .. } => "There was an error related to an archive file. Details:\n\n", |
|
||||||
Error::Http { .. } => "There wasn an HTTP error. Details:\n\n", |
|
||||||
} |
|
||||||
.to_string() |
|
||||||
} |
|
||||||
} |
|
@ -1,47 +0,0 @@ |
|||||||
use error::Error; |
|
||||||
use failure; |
|
||||||
|
|
||||||
pub fn curl(url: &str) -> Result<Vec<u8>, failure::Error> { |
|
||||||
let mut data = Vec::new(); |
|
||||||
|
|
||||||
let mut easy = curl::easy::Easy::new(); |
|
||||||
with_url_context(url, easy.follow_location(true))?; |
|
||||||
with_url_context(url, easy.url(url))?; |
|
||||||
transfer(url, &mut easy, &mut data)?; |
|
||||||
|
|
||||||
let status_code = with_url_context(url, easy.response_code())?; |
|
||||||
if 200 <= status_code && status_code < 300 { |
|
||||||
Ok(data) |
|
||||||
} else { |
|
||||||
Err(Error::http(&format!( |
|
||||||
"received a bad HTTP status code ({}) when requesting {}", |
|
||||||
status_code, url |
|
||||||
)) |
|
||||||
.into()) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
fn with_url_context<T, E>(url: &str, r: Result<T, E>) -> Result<T, impl failure::Fail> |
|
||||||
where |
|
||||||
Result<T, E>: failure::ResultExt<T, E>, |
|
||||||
{ |
|
||||||
use failure::ResultExt; |
|
||||||
r.with_context(|_| format!("when requesting {}", url)) |
|
||||||
} |
|
||||||
|
|
||||||
fn transfer( |
|
||||||
url: &str, |
|
||||||
easy: &mut curl::easy::Easy, |
|
||||||
data: &mut Vec<u8>, |
|
||||||
) -> Result<(), failure::Error> { |
|
||||||
let mut transfer = easy.transfer(); |
|
||||||
with_url_context( |
|
||||||
url, |
|
||||||
transfer.write_function(|part| { |
|
||||||
data.extend_from_slice(part); |
|
||||||
Ok(part.len()) |
|
||||||
}), |
|
||||||
)?; |
|
||||||
with_url_context(url, transfer.perform())?; |
|
||||||
Ok(()) |
|
||||||
} |
|
@ -1,76 +0,0 @@ |
|||||||
use slog::Logger; |
|
||||||
use std::fs; |
|
||||||
use std::io; |
|
||||||
use std::path::{Path, PathBuf}; |
|
||||||
use target; |
|
||||||
use which::which; |
|
||||||
|
|
||||||
/// Get the path for a crate's directory of locally-installed binaries.
|
|
||||||
///
|
|
||||||
/// This does not check whether or ensure that the directory exists.
|
|
||||||
pub fn local_bin_dir(crate_path: &Path) -> PathBuf { |
|
||||||
crate_path.join("bin") |
|
||||||
} |
|
||||||
|
|
||||||
/// Ensure that the crate's directory for locally-installed binaries exists.
|
|
||||||
pub fn ensure_local_bin_dir(crate_path: &Path) -> io::Result<()> { |
|
||||||
fs::create_dir_all(local_bin_dir(crate_path)) |
|
||||||
} |
|
||||||
|
|
||||||
/// Get the path for where `bin` would be if we have a crate-local install for
|
|
||||||
/// it.
|
|
||||||
///
|
|
||||||
/// This does *not* check whether there is a file at that path or not.
|
|
||||||
///
|
|
||||||
/// This will automatically add the `.exe` extension for windows.
|
|
||||||
pub fn local_bin_path(crate_path: &Path, bin: &str) -> PathBuf { |
|
||||||
let mut p = local_bin_dir(crate_path).join(bin); |
|
||||||
if target::WINDOWS { |
|
||||||
p.set_extension("exe"); |
|
||||||
} |
|
||||||
p |
|
||||||
} |
|
||||||
|
|
||||||
/// Get the local (at `$CRATE/bin/$BIN`; preferred) or global (on `$PATH`) path
|
|
||||||
/// for the given binary.
|
|
||||||
///
|
|
||||||
/// If this function returns `Some(path)`, then a file at that path exists (or
|
|
||||||
/// at least existed when we checked! In general, we aren't really worried about
|
|
||||||
/// racing with an uninstall of a tool that we rely on.)
|
|
||||||
pub fn bin_path(log: &Logger, crate_path: &Path, bin: &str) -> Option<PathBuf> { |
|
||||||
assert!(!bin.ends_with(".exe")); |
|
||||||
debug!(log, "Searching for {} binary...", bin); |
|
||||||
|
|
||||||
// Return the path to the local binary, if it exists.
|
|
||||||
let local_path = |crate_path: &Path| -> Option<PathBuf> { |
|
||||||
let p = local_bin_path(crate_path, bin); |
|
||||||
debug!(log, "Checking for local {} binary at {}", bin, p.display()); |
|
||||||
if p.is_file() { |
|
||||||
Some(p) |
|
||||||
} else { |
|
||||||
None |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
// Return the path to the global binary, if it exists.
|
|
||||||
let global_path = || -> Option<PathBuf> { |
|
||||||
debug!(log, "Looking for global {} binary on $PATH", bin); |
|
||||||
if let Ok(p) = which(bin) { |
|
||||||
Some(p) |
|
||||||
} else { |
|
||||||
None |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
local_path(crate_path) |
|
||||||
.or_else(global_path) |
|
||||||
.map(|p| { |
|
||||||
let p = p.canonicalize().unwrap_or(p); |
|
||||||
debug!(log, "Using {} binary at {}", bin, p.display()); |
|
||||||
p |
|
||||||
}) |
|
||||||
.or_else(|| { |
|
||||||
debug!(log, "Could not find {} binary.", bin); |
|
||||||
None |
|
||||||
}) |
|
||||||
} |
|
@ -1,8 +0,0 @@ |
|||||||
//! Information about the target wasm-pack is currently being compiled for.
|
|
||||||
//!
|
|
||||||
//! That is, whether we are building wasm-pack for windows vs linux, and x86 vs
|
|
||||||
//! x86-64, etc.
|
|
||||||
|
|
||||||
#![allow(missing_docs)] |
|
||||||
|
|
||||||
pub const WINDOWS: bool = cfg!(target_os = "windows"); |
|
@ -1,117 +0,0 @@ |
|||||||
extern crate binary_install; |
|
||||||
#[macro_use] |
|
||||||
extern crate slog; |
|
||||||
extern crate slog_async; |
|
||||||
extern crate slog_term; |
|
||||||
|
|
||||||
use binary_install::path::{bin_path, ensure_local_bin_dir, local_bin_path}; |
|
||||||
use slog::Drain; |
|
||||||
use std::env; |
|
||||||
use std::fs; |
|
||||||
use std::io; |
|
||||||
use std::path::PathBuf; |
|
||||||
|
|
||||||
fn logger() -> slog::Logger { |
|
||||||
let decorator = slog_term::TermDecorator::new().build(); |
|
||||||
let drain = slog_term::FullFormat::new(decorator).build().fuse(); |
|
||||||
let drain = slog_async::Async::new(drain).build().fuse(); |
|
||||||
slog::Logger::root(drain, o!()) |
|
||||||
} |
|
||||||
|
|
||||||
fn get_tests_bin_path() -> PathBuf { |
|
||||||
let path = env::temp_dir(); |
|
||||||
path.join("tests") |
|
||||||
} |
|
||||||
|
|
||||||
#[test] |
|
||||||
#[cfg(not(target_os = "windows"))] |
|
||||||
fn get_local_bin_path_should_return_a_path() { |
|
||||||
let crate_path = get_tests_bin_path(); |
|
||||||
let expected_path = crate_path.join("bin/wasm-bindgen"); |
|
||||||
|
|
||||||
let result = local_bin_path(&crate_path, "wasm-bindgen"); |
|
||||||
|
|
||||||
assert_eq!(expected_path, result); |
|
||||||
} |
|
||||||
|
|
||||||
#[test] |
|
||||||
#[cfg(target_os = "windows")] |
|
||||||
fn get_local_bin_path_should_return_with_exe_for_windows() { |
|
||||||
let crate_path = get_tests_bin_path(); |
|
||||||
|
|
||||||
let expected_path = crate_path.join("bin/wasm-bindgen.exe"); |
|
||||||
|
|
||||||
let result = local_bin_path(crate_path, "wasm-bindgen"); |
|
||||||
|
|
||||||
assert_eq!(expected_path, result); |
|
||||||
} |
|
||||||
|
|
||||||
#[test] |
|
||||||
fn ensure_local_bin_dir_should_return_ok_for_folder_that_exists() { |
|
||||||
let crate_path = get_tests_bin_path().join("bin2"); |
|
||||||
|
|
||||||
fs::create_dir_all(crate_path.to_owned()).unwrap(); |
|
||||||
|
|
||||||
let result = ensure_local_bin_dir(&crate_path); |
|
||||||
|
|
||||||
assert!(result.is_ok()); |
|
||||||
|
|
||||||
fs::remove_dir_all(crate_path).unwrap(); |
|
||||||
} |
|
||||||
|
|
||||||
#[test] |
|
||||||
fn ensure_local_bin_dir_should_create_folder_if_it_doesnt_exist() { |
|
||||||
let crate_path = get_tests_bin_path().join("bin3"); |
|
||||||
|
|
||||||
// Make sure that the folder doesn't exist
|
|
||||||
// before we call ensure_local_bin_dir();
|
|
||||||
let dir = fs::read_dir(crate_path.to_owned()); |
|
||||||
let dir_error = dir.err().unwrap(); |
|
||||||
assert_eq!(dir_error.kind(), io::ErrorKind::NotFound); |
|
||||||
|
|
||||||
let result = ensure_local_bin_dir(&crate_path); |
|
||||||
|
|
||||||
assert!(result.is_ok()); |
|
||||||
|
|
||||||
// Make sure that the directory actually exists.
|
|
||||||
let dir = fs::read_dir(crate_path.to_owned()); |
|
||||||
assert!(dir.is_ok()); |
|
||||||
|
|
||||||
fs::remove_dir_all(crate_path).unwrap(); |
|
||||||
} |
|
||||||
|
|
||||||
#[test] |
|
||||||
fn bin_path_should_return_some_for_path_that_exists() { |
|
||||||
let crate_path = get_tests_bin_path(); |
|
||||||
let bin_file = "wasm-bindgen"; |
|
||||||
let full_bin_path = crate_path.join("bin"); |
|
||||||
let path_with_bin_file = full_bin_path.join(bin_file); |
|
||||||
|
|
||||||
fs::create_dir_all(full_bin_path.to_owned()).unwrap(); |
|
||||||
fs::File::create(path_with_bin_file.to_owned()).unwrap(); |
|
||||||
|
|
||||||
let result = bin_path(&logger(), &crate_path, bin_file); |
|
||||||
|
|
||||||
assert!(result.is_some()); |
|
||||||
assert_eq!(path_with_bin_file, result.unwrap()); |
|
||||||
|
|
||||||
fs::remove_dir_all(full_bin_path).unwrap(); |
|
||||||
} |
|
||||||
|
|
||||||
#[test] |
|
||||||
fn bin_path_should_return_none_for_path_that_does_not_exists() { |
|
||||||
let crate_path = get_tests_bin_path(); |
|
||||||
let bin_file = "wasm-binfile"; |
|
||||||
let full_bin_path = crate_path.join("bin_path"); |
|
||||||
let path_with_bin_file = full_bin_path.join(bin_file); |
|
||||||
|
|
||||||
// Make sure that the folder doesn't exist
|
|
||||||
// before we call bin_path();
|
|
||||||
let file = fs::File::open(path_with_bin_file.to_owned()); |
|
||||||
let file_error = file.err().unwrap(); |
|
||||||
assert_eq!(file_error.kind(), io::ErrorKind::NotFound); |
|
||||||
|
|
||||||
let result = bin_path(&logger(), &crate_path, bin_file); |
|
||||||
|
|
||||||
assert!(result.is_none()); |
|
||||||
} |
|
@ -1,168 +0,0 @@ |
|||||||
extern crate binary_install; |
|
||||||
extern crate curl; |
|
||||||
extern crate failure; |
|
||||||
extern crate flate2; |
|
||||||
extern crate tar; |
|
||||||
|
|
||||||
use binary_install::{error::Error, install_binaries_from_targz_at_url}; |
|
||||||
use flate2::write::GzEncoder; |
|
||||||
use flate2::Compression; |
|
||||||
use std::env; |
|
||||||
use std::fs::{File, OpenOptions}; |
|
||||||
use std::io::{self, Read, Write}; |
|
||||||
use std::net::TcpListener; |
|
||||||
use std::path::Path; |
|
||||||
use std::thread; |
|
||||||
|
|
||||||
const SERVER_HOST: &'static str = "localhost"; |
|
||||||
|
|
||||||
fn start_server(port: u32, tarball: Option<Vec<u8>>) -> thread::JoinHandle<TcpListener> { |
|
||||||
thread::spawn(move || { |
|
||||||
let listener = TcpListener::bind(format!("{}:{}", SERVER_HOST, port)).unwrap(); |
|
||||||
|
|
||||||
for stream in listener.incoming() { |
|
||||||
let mut stream = stream.unwrap(); |
|
||||||
|
|
||||||
let mut buffer = [0; 512]; |
|
||||||
|
|
||||||
stream.read(&mut buffer).unwrap(); |
|
||||||
|
|
||||||
let response = "HTTP/1.1 200 OK\r\n\r\n"; |
|
||||||
|
|
||||||
stream.write(response.as_bytes()).unwrap(); |
|
||||||
|
|
||||||
match tarball.to_owned() { |
|
||||||
Some(tar) => { |
|
||||||
stream.write(tar.as_ref()).unwrap(); |
|
||||||
} |
|
||||||
None => {} |
|
||||||
} |
|
||||||
|
|
||||||
stream.flush().unwrap(); |
|
||||||
} |
|
||||||
listener |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
fn create_tarball(binary_name: &str) -> Result<Vec<u8>, io::Error> { |
|
||||||
let temp_dir = env::temp_dir(); |
|
||||||
let tar = OpenOptions::new() |
|
||||||
.create(true) |
|
||||||
.read(true) |
|
||||||
.write(true) |
|
||||||
.open(temp_dir.join("foo.tar.gz"))?; |
|
||||||
|
|
||||||
let mut file = OpenOptions::new() |
|
||||||
.create(true) |
|
||||||
.read(true) |
|
||||||
.write(true) |
|
||||||
.open(temp_dir.join(binary_name))?; |
|
||||||
|
|
||||||
let mut encoder = GzEncoder::new(tar, Compression::default()); |
|
||||||
{ |
|
||||||
let mut archive = tar::Builder::new(&mut encoder); |
|
||||||
archive.append_file(binary_name, &mut file)?; |
|
||||||
} |
|
||||||
|
|
||||||
let mut contents = vec![]; |
|
||||||
|
|
||||||
encoder.finish()?; |
|
||||||
|
|
||||||
File::open(temp_dir.join("foo.tar.gz"))?.read_to_end(&mut contents)?; |
|
||||||
|
|
||||||
Ok(contents) |
|
||||||
} |
|
||||||
|
|
||||||
#[test] |
|
||||||
fn install_binaries_from_targz_at_url_should_return_http_error_for_bad_url() { |
|
||||||
let crate_path = Path::new(""); |
|
||||||
let url = ""; |
|
||||||
let binaries = vec![""]; |
|
||||||
|
|
||||||
let result = install_binaries_from_targz_at_url(crate_path, url, binaries); |
|
||||||
assert!(result.is_err()); |
|
||||||
|
|
||||||
let err = result.err().unwrap(); |
|
||||||
let err = err.downcast_ref::<Error>().unwrap(); |
|
||||||
|
|
||||||
let expected_message = format!("when requesting {}", url); |
|
||||||
|
|
||||||
match err { |
|
||||||
Error::Http { message } => assert_eq!(&expected_message, message), |
|
||||||
_ => panic!("Wrong error returned"), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
#[test] |
|
||||||
fn install_binaries_from_targz_at_url_should_return_archive_error_when_tarball_is_missing() { |
|
||||||
let server_port = 7878; |
|
||||||
let url = format!("http://{}:{}", SERVER_HOST, server_port); |
|
||||||
let crate_path = Path::new(""); |
|
||||||
let binaries = vec![""]; |
|
||||||
|
|
||||||
// Spin up a local TcpListener.
|
|
||||||
start_server(server_port, None); |
|
||||||
|
|
||||||
let result = install_binaries_from_targz_at_url(crate_path, &url, binaries); |
|
||||||
assert!(result.is_err()); |
|
||||||
|
|
||||||
let err = result.err().unwrap(); |
|
||||||
let err = err.downcast_ref::<Error>().unwrap(); |
|
||||||
|
|
||||||
let expected_message = format!( |
|
||||||
"Invalid tarball at {}. Inner error: failed to fill whole buffer", |
|
||||||
url |
|
||||||
); |
|
||||||
|
|
||||||
match err { |
|
||||||
Error::Archive { message } => assert_eq!(&expected_message, message), |
|
||||||
_ => panic!("Wrong error returned"), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
#[test] |
|
||||||
fn install_binaries_from_targz_at_url_should_return_archive_error_when_tarball_does_not_include_all_files( |
|
||||||
) { |
|
||||||
let server_port = 7879; |
|
||||||
let url = format!("http://{}:{}", SERVER_HOST, server_port); |
|
||||||
let crate_path = Path::new(""); |
|
||||||
let binaries = vec!["wasm-pack"]; |
|
||||||
|
|
||||||
// Create a temporary tarball.
|
|
||||||
let tarball = create_tarball("foo.txt").ok(); |
|
||||||
// Spin up a local TcpListener.
|
|
||||||
start_server(server_port, tarball); |
|
||||||
|
|
||||||
let result = install_binaries_from_targz_at_url(crate_path, &url, binaries); |
|
||||||
assert!(result.is_err()); |
|
||||||
|
|
||||||
let err = result.err().unwrap(); |
|
||||||
let err = err.downcast_ref::<Error>().unwrap(); |
|
||||||
|
|
||||||
let expected_message = format!( |
|
||||||
"the tarball at {} was missing expected executables: {}", |
|
||||||
url, "wasm-pack" |
|
||||||
); |
|
||||||
|
|
||||||
match err { |
|
||||||
Error::Archive { message } => assert_eq!(&expected_message, message), |
|
||||||
_ => panic!("Wrong error returned"), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
#[test] |
|
||||||
fn install_binaries_from_targz_at_url_should_return_ok_if_binary_is_found() { |
|
||||||
let server_port = 7880; |
|
||||||
let url = format!("http://{}:{}", SERVER_HOST, server_port); |
|
||||||
let binary_name = "wasm-pack"; |
|
||||||
let crate_path = Path::new(""); |
|
||||||
let binaries = vec![binary_name]; |
|
||||||
|
|
||||||
// Create a temporary tarball.
|
|
||||||
let tarball = create_tarball(binary_name).ok(); |
|
||||||
// Spin up a local TcpListener.
|
|
||||||
start_server(server_port, tarball); |
|
||||||
|
|
||||||
let result = install_binaries_from_targz_at_url(crate_path, &url, binaries); |
|
||||||
assert!(result.is_ok()); |
|
||||||
} |
|
Loading…
Reference in new issue