Commit 50e3b3d3 authored by PERE Alexandre's avatar PERE Alexandre

Merge branch 'develop' into 'master'

V0.3.0

See merge request !18
parents 72f9e61e 66e5f529
......@@ -5,3 +5,4 @@ target/
.vscode
Cargo.lock
test_env_vars
*.orig
......@@ -2,7 +2,6 @@
members = [
"liborchestra",
"runaway-cli",
"remote-leak",
"ssh2-rs",
"libssh2-sys"]
......
[package]
name = "liborchestra"
version = "0.0.2"
version = "0.3.0"
authors = ["Alexandre Péré <alexandre.pere@protonmail.com>"]
edition = "2018"
[dependencies]
log = "0.3"
env_logger = "0.6"
chrono = { version = "0.4", features = ["serde"] }
serde = "1.0"
serde_derive = "1.0"
serde_yaml = "0.7"
serde_json = "1.0"
regex = "1"
futures-preview = { version = "=0.3.0-alpha.17", features = ["async-await", "nightly"] }
futures-preview = { version = "=0.3.0-alpha.19", features = ["async-await"] }
yaml-rust="0.4"
rust-crypto = "0.2"
uuid = { version = "0.6", features = ["serde", "v4"] }
rpassword = "0.0.4"
ssh2 = "0.3.3"
shells = "0.2.0"
dirs = "1.0"
chashmap = "2.2.2"
url = "1.7.2"
git2 = {version = "0.8"}
crossbeam = "0.7.1"
typetag = "0.1"
tar = "0.4.26"
ignore = "0.4.7"
fasthash = "0.4.0"
sha-1 = "0.8.1"
walkdir = "2.2.7"
shells = "0.2"
libc = "0.2"
globset = "0.4.4"
tracing = "0.1.10"
tracing-subscriber = "0.1.6"
tracing-attributes = "0.1.5"
tracing-futures = {version = "0.1.0", features=["futures-preview"]}
derivative = "1.0.3"
arrayvec = "0.5.1"
lazy_static = "1.4.0"
[lib]
name="liborchestra"
......
This diff is collapsed.
This diff is collapsed.
//! liborchestra/error.rs
//! Author: Alexandre Péré
//!
//! This module contains module-level error type to interface with the error types implemented at
//! the sub-module level.
......@@ -8,13 +7,28 @@
//------------------------------------------------------------------------------------------ IMPORTS
use crate::{ssh, repository, misc, primitives, derive_from_error};
use crate::{ssh, repository, misc, commons};
use std::{io, error, fmt};
use regex;
//use git2;
use yaml_rust;
//------------------------------------------------------------------------------------------- MACROS
#[macro_export]
macro_rules! derive_from_error {
($error:ident, $from_type:ty, $variant:ident) => {
impl From<$from_type> for $error {
fn from(err: $from_type) -> $error {
$error::$variant(err)
}
}
}
}
//-------------------------------------------------------------------------------------------- ERROR
......@@ -31,7 +45,7 @@ pub enum Error {
Git(git2::Error),
Repository(repository::Error),
Misc(misc::Error),
Primitives(primitives::Error),
Commons(commons::Error),
}
impl error::Error for Error {}
......@@ -48,7 +62,7 @@ impl fmt::Display for Error {
Error::Git(ref s) => write!(f, "Git related error happened:\n{}", s),
Error::Repository(ref s) => write!(f, "Repository related error happened:\n{}", s),
Error::Misc(ref s) => write!(f, "Misc related error happened:\n{}", s),
Error::Primitives(ref s) => write!(f, "Primitives related error occurred:\n{}", s)
Error::Commons(ref s) => write!(f, "Primitives related error occurred:\n{}", s)
}
}
}
......@@ -61,4 +75,4 @@ derive_from_error!(Error, ssh::Error, Ssh);
derive_from_error!(Error, git2::Error, Git);
derive_from_error!(Error, repository::Error, Repository);
derive_from_error!(Error, misc::Error, Misc);
derive_from_error!(Error, primitives::Error, Primitives);
\ No newline at end of file
derive_from_error!(Error, commons::Error, Commons);
\ No newline at end of file
This diff is collapsed.
// liborchestra/misc.rs
//
// Author: Alexandre Péré
///
/// A few miscellaneous functions publicly available.
//! liborchestra/misc.rs
//! Author: Alexandre Péré
//!
//! A few miscellaneous available library wide.
//------------------------------------------------------------------------------------------ IMPORTS
// IMPORTS
use std::{process, path, fs, error, fmt};
use regex;
use super::CMPCONF_RPATH;
use tracing::{self, warn, debug};
use super::commons::OutputBuf;
use super::timer::TimerHandle;
//------------------------------------------------------------------------------------------- STATIC
lazy_static! {
pub static ref TIMER: TimerHandle = TimerHandle::spawn().expect("Failed to spawn timer.");
}
//------------------------------------------------------------------------------------------- ERRORS
// ERRORS
#[derive(Debug)]
pub enum Error {
InvalidRepository,
......@@ -27,7 +42,163 @@ impl fmt::Display for Error {
}
}
////////////////////////////////////////////////////////////////////////////////////////// FUNCTIONS
//------------------------------------------------------------------------------------------- MACROS
/// This macro allows to asynchronously wait for (at least) a given time. This means that the thread
/// is yielded when it is done. For now, it creates a separate thread each time a sleep is needed,
/// which is far from ideal.
#[macro_export]
macro_rules! async_sleep {
($dur: expr) => {
{
use crate::misc::TIMER;
(*TIMER).async_sleep($dur).await.unwrap();
}
};
}
/// This macro allows to intercept a wouldblock error returned by the expression evaluation, and
/// awaits for 1 ns (at least) before retrying.
#[macro_export]
macro_rules! await_wouldblock_io {
($expr:expr) => {
{
use tracing::trace_span;
let span = trace_span!("await_wouldblock_io!");
let _guard = span.enter();
loop{
match $expr {
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
async_sleep!(std::time::Duration::from_millis(2))
}
res => break res,
}
}
}
}
}
/// This macro allows to intercept a wouldblock error returned by the expression evaluation, and
/// awaits for 1 ns (at least) before retrying.
#[macro_export]
macro_rules! await_wouldblock_ssh {
($expr:expr) => {
{
use tracing::trace_span;
let span = trace_span!("await_wouldblock_ssh!");
let _guard = span.enter();
loop{
match $expr {
Err(ref e) if e.code() == -37 => {
async_sleep!(std::time::Duration::from_millis(2))
}
Err(ref e) if e.code() == -21 => {
async_sleep!(std::time::Duration::from_millis(2))
}
res => break res,
}
}
}
}
}
/// This macro allows to retry an ssh expression if the error code received was $code. It allows to
/// retry commands that fails every now and then for a limited amount of time.
#[macro_export]
macro_rules! await_retry_n_ssh {
($expr:expr, $nb:expr, $($code:expr),*) => {
{
use tracing::trace_span;
let span = trace_span!("await_retry_n_ssh!");
let _guard = span.enter();
let nb = $nb as usize;
let mut i = 1 as usize;
loop{
match $expr {
Err(e) => {
if i == nb {
break Err(e)
}
$(
else if e.code() == $code as i32 {
async_sleep!(std::time::Duration::from_millis(2));
i += 1;
}
)*
}
res => {
break res
}
}
}
}
}
}
/// This macro allows to retry an ssh expression if the error code received was $code. It allows to
/// retry commands that fail but must be retried until it's ok. For example
#[macro_export]
macro_rules! await_retry_ssh {
($expr:expr, $($code:expr),*) => {
{
use tracing::trace_span;
let span = trace_span!("await_retry_n_ssh!");
let _guard = span.enter();
loop{
match $expr {
Err(e) => {
$( if e.code() == $code as i32 {
async_sleep!(std::time::Duration::from_millis(2));
} else )*
{
break Err(e)
}
}
res => {
break res
}
}
}
}
}
}
/// This macro allows to retry an expression it returns an error. It allows to
/// retry commands that fails every now and then for a limited amount of time.
#[macro_export]
macro_rules! await_retry_n {
($expr:expr, $nb:expr) => {
{
use tracing::trace_span;
let span = trace_span!("await_retry_n!");
let _guard = span.enter();
let nb = $nb as usize;
let mut i = 1 as usize;
loop{
match $expr {
Err(e) => {
if i == nb {
break Err(e)
}
else{
async_sleep!(std::time::Duration::from_millis(2));
i += 1;
}
}
res => {
break res
}
}
}
}
}
}
//---------------------------------------------------------------------------------------- FUNCTIONS
/// Returns a tuple containing the git and git-lfs versions.
pub fn check_git_lfs_versions() -> Result<(String, String), crate::Error> {
......@@ -53,7 +224,8 @@ pub fn check_git_lfs_versions() -> Result<(String, String), crate::Error> {
/// Returns the absolute path to the higher expegit folder starting from `start_path`.
pub fn search_expegit_root(start_path: &path::PathBuf) -> Result<path::PathBuf, crate::Error> {
debug!("Searching expegit repository root from {}", fs::canonicalize(start_path).unwrap().to_str().unwrap());
debug!("Searching expegit repository root from {}",
fs::canonicalize(start_path).unwrap().to_str().unwrap());
let start_path = fs::canonicalize(start_path)?;
if start_path.is_file() { panic!("Should provide a folder path.") };
// We add a dummy folder that will be popped directly to check for .
......@@ -117,9 +289,38 @@ pub fn get_hostname() -> Result<String, crate::Error> {
Ok(format!("{}@{}", user, host))
}
use std::process::{Output};
use std::os::unix::process::ExitStatusExt;
/// Compacts a list of outputs in a single output:
/// + The stdouts are concatenated
/// + The stderrs are concatenated
/// + The last error code is kept
pub fn compact_outputs(outputs: Vec<Output>) -> Output{
let mut outputs = outputs;
outputs.iter_mut()
.fold(Output{status: ExitStatusExt::from_raw(0), stdout: Vec::new(), stderr: Vec::new()},
|mut acc, o| {
acc.stdout.append(&mut o.stdout);
acc.stderr.append(&mut o.stderr);
acc.status = o.status;
acc
})
}
/// Formats commands and output properly
pub fn format_commands_outputs(commands: &Vec<String>, outputs: &Vec<Output>) -> String{
commands.iter().zip(outputs.iter().map(|o| OutputBuf::from(o.to_owned())))
.fold(String::new(), |mut acc, (c, o)|{
acc.push_str(&format!("{:?} :\n stdout: {:?}\n stderr: {:?}\n ecode: {}\n",
c, o.stdout, o.stderr, o.ecode));
acc
})
}
//-------------------------------------------------------------------------------------------- TESTS
// TESTS
#[cfg(test)]
mod test {
use std::fs;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -98,8 +98,8 @@ fn main() {
cfg.define("LIBSSH2_OPENSSL", None);
cfg.define("HAVE_LIBCRYPT32", None);
cfg.define("HAVE_EVP_AES_128_CTR", None);
cfg.define("LIBSSH2DEBUG", None);
if is_debug{
cfg.define("LIBSSH2DEBUG", None);
cfg.define("HAVE_GETTIMEOFDAY", None);
cfg.define("ENABLE_DEBUG_LOGGING", Some("ON"));
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment