Rewrite imag binary in Rust
This commit is contained in:
parent
9f528fb929
commit
27124c2a83
3 changed files with 184 additions and 79 deletions
10
bin/Cargo.toml
Normal file
10
bin/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "imag"
|
||||
version = "0.1.0"
|
||||
authors = ["Matthias Beyer <mail@beyermatthias.de>"]
|
||||
|
||||
[dependencies]
|
||||
version = "2.0"
|
||||
walkdir = "0.1.5"
|
||||
crossbeam = "0.2.9"
|
||||
|
79
bin/imag
79
bin/imag
|
@ -1,79 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
version() {
|
||||
echo "0.1.0"
|
||||
}
|
||||
|
||||
help() {
|
||||
local cmds="$(commands)"
|
||||
|
||||
echo " _ ";
|
||||
echo " (_)_ __ ___ __ _ __ _ ";
|
||||
echo " | | '_ \` _ \ / _\` |/ _\` |";
|
||||
echo " | | | | | | | (_| | (_| |";
|
||||
echo " |_|_| |_| |_|\__,_|\__, |";
|
||||
echo " |___/ ";
|
||||
echo " -------------------------";
|
||||
cat <<EOS
|
||||
|
||||
Usage: imag [--version | --versions | -h | --help] <command> <args...>
|
||||
|
||||
imag - the personal information management suite for the commandline
|
||||
|
||||
imag is a PIM suite for the commandline. It consists of several commands,
|
||||
called "modules". Each module implements one PIM aspect and all of these
|
||||
modules can be used independently.
|
||||
|
||||
Available commands:
|
||||
$(for cmd in $cmds; do
|
||||
echo -e "\t$(echo $cmd | sed -r 's,(.*)/imag-(.*),\2,')";
|
||||
done)
|
||||
|
||||
Call a command with "imag <command> <args>"
|
||||
Each command can be called with "--help" to get the respective helptext.
|
||||
|
||||
Please visit https://github.com/matthiasbeyer/imag to view the source code,
|
||||
follow the development of imag or maybe even contribute to imag.
|
||||
|
||||
imag is free software. It is released under the terms of LGPLv2.1
|
||||
|
||||
(c) 2016 Matthias Beyer and contributors
|
||||
EOS
|
||||
}
|
||||
|
||||
commands() {
|
||||
[[ ! -z "$IMAG_IS_THE_SHIT" ]] && \
|
||||
find $IMAG_IS_THE_SHIT -type f -iname "imag-*" -print 2>/dev/null
|
||||
find ${PATH//:/ } -maxdepth 1 -type f -iname "imag-*" -print 2>/dev/null
|
||||
}
|
||||
|
||||
main() {
|
||||
case $1 in
|
||||
--versions)
|
||||
echo -n "imag "; version
|
||||
for command in $(commands); do
|
||||
$command --version
|
||||
done
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--version)
|
||||
version
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--help | -h)
|
||||
help
|
||||
exit 0
|
||||
;;
|
||||
|
||||
*)
|
||||
local cmd=$1; shift
|
||||
local executable=$(commands | grep $cmd | head -n 1)
|
||||
exec $executable $*
|
||||
;;
|
||||
|
||||
esac
|
||||
}
|
||||
|
||||
main $*
|
174
bin/src/main.rs
Normal file
174
bin/src/main.rs
Normal file
|
@ -0,0 +1,174 @@
|
|||
extern crate crossbeam;
|
||||
#[macro_use] extern crate version;
|
||||
extern crate walkdir;
|
||||
|
||||
use std::env;
|
||||
use std::process::exit;
|
||||
use std::process::Command;
|
||||
use std::process::Stdio;
|
||||
use std::io::ErrorKind;
|
||||
|
||||
use walkdir::WalkDir;
|
||||
use crossbeam::*;
|
||||
|
||||
fn help(cmds: Vec<String>) {
|
||||
println!(r#"
|
||||
|
||||
_
|
||||
(_)_ __ ___ __ _ __ _
|
||||
| | '_ \` _ \/ _\`|/ _\`|
|
||||
| | | | | | | (_| | (_| |
|
||||
|_|_| |_| |_|\__,_|\__, |
|
||||
|___/
|
||||
-------------------------
|
||||
|
||||
Usage: imag [--version | --versions | -h | --help] <command> <args...>
|
||||
|
||||
imag - the personal information management suite for the commandline
|
||||
|
||||
imag is a PIM suite for the commandline. It consists of several commands,
|
||||
called "modules". Each module implements one PIM aspect and all of these
|
||||
modules can be used independently.
|
||||
|
||||
Available commands:
|
||||
"#);
|
||||
|
||||
for cmd in cmds.iter() {
|
||||
println!("\t{}", cmd);
|
||||
}
|
||||
|
||||
println!(r#"
|
||||
|
||||
Call a command with 'imag <command> <args>'
|
||||
Each command can be called with "--help" to get the respective helptext.
|
||||
|
||||
Please visit https://github.com/matthiasbeyer/imag to view the source code,
|
||||
follow the development of imag or maybe even contribute to imag.
|
||||
|
||||
imag is free software. It is released under the terms of LGPLv2.1
|
||||
|
||||
(c) 2016 Matthias Beyer and contributors"#);
|
||||
}
|
||||
|
||||
fn get_commands() -> Vec<String> {
|
||||
let path = env::var("PATH");
|
||||
if path.is_err() {
|
||||
println!("PATH error: {:?}", path);
|
||||
exit(1);
|
||||
}
|
||||
let pathelements = path.unwrap();
|
||||
let pathelements = pathelements.split(":");
|
||||
|
||||
let joinhandles : Vec<ScopedJoinHandle<Vec<String>>> = pathelements
|
||||
.map(|elem| {
|
||||
crossbeam::scope(|scope| {
|
||||
scope.spawn(|| {
|
||||
WalkDir::new(elem)
|
||||
.max_depth(1)
|
||||
.into_iter()
|
||||
.filter(|path| {
|
||||
match path {
|
||||
&Ok(ref path) => path.path().starts_with(format!("{}/imag-", elem)),
|
||||
&Err(_) => false,
|
||||
}
|
||||
})
|
||||
.filter_map(|x| x.ok())
|
||||
.map(|path| {
|
||||
path.path()
|
||||
.to_str()
|
||||
.map(String::from)
|
||||
})
|
||||
.filter_map(|x| x)
|
||||
.collect()
|
||||
})
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut execs = vec![];
|
||||
for joinhandle in joinhandles.into_iter() {
|
||||
let mut v = joinhandle.join();
|
||||
execs.append(&mut v);
|
||||
}
|
||||
|
||||
execs
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let commands = get_commands();
|
||||
let mut args = env::args();
|
||||
let _ = args.next();
|
||||
let first_arg = match args.next() {
|
||||
Some(s) => s,
|
||||
None => {
|
||||
help(commands);
|
||||
exit(0);
|
||||
},
|
||||
};
|
||||
|
||||
match &first_arg[..] {
|
||||
"--help" | "-h" => {
|
||||
help(commands);
|
||||
exit(0);
|
||||
},
|
||||
|
||||
"--version" => println!("imag {}", &version!()[..]),
|
||||
|
||||
"--versions" => {
|
||||
let mut result = vec![];
|
||||
for command in commands.iter() {
|
||||
result.push(crossbeam::scope(|scope| {
|
||||
scope.spawn(|| {
|
||||
let v = Command::new(command).arg("--version").output();
|
||||
match v {
|
||||
Ok(v) => match String::from_utf8(v.stdout) {
|
||||
Ok(s) => format!("{} -> {}", command, s),
|
||||
Err(e) => format!("Failed calling {} -> {:?}", command, e),
|
||||
},
|
||||
Err(e) => format!("Failed calling {} -> {:?}", command, e),
|
||||
}
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
for versionstring in result.into_iter().map(|handle| handle.join()) {
|
||||
println!("{}", versionstring);
|
||||
}
|
||||
},
|
||||
|
||||
s => {
|
||||
match Command::new(format!("imag-{}", s))
|
||||
.stdin(Stdio::inherit())
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit())
|
||||
.spawn()
|
||||
.and_then(|mut handle| handle.wait())
|
||||
{
|
||||
Ok(exit_status) => {
|
||||
if !exit_status.success() {
|
||||
println!("{} exited with non-zero exit code", s);
|
||||
exit(exit_status.code().unwrap_or(42));
|
||||
}
|
||||
},
|
||||
|
||||
Err(e) => {
|
||||
match e.kind() {
|
||||
ErrorKind::NotFound => {
|
||||
println!("No such command: 'imag-{}'", s);
|
||||
exit(2);
|
||||
},
|
||||
ErrorKind::PermissionDenied => {
|
||||
println!("No permission to execute: 'imag-{}'", s);
|
||||
exit(1);
|
||||
},
|
||||
_ => {
|
||||
println!("Error spawning: {:?}", e);
|
||||
exit(1337);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue