Skip to content

Commit

Permalink
refactor: a lot of cleanup and rework with anyhow
Browse files Browse the repository at this point in the history
Removed direct libc usage and using users crate instead
Using anyhow crate everywhere so there is less messy code
  • Loading branch information
sandorex committed Nov 2, 2024
1 parent 2e238e4 commit c14a5ca
Show file tree
Hide file tree
Showing 24 changed files with 873 additions and 832 deletions.
15 changes: 13 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ serde = { version = "1.0.204", features = ["derive"] }
toml = "0.8.19"
code-docs-rs = "0.1.0"
shellexpand = "3.1.0"
anyhow = "1.0.86"
users = "0.11.0"

[build-dependencies]
anyhow = "1.0.86"
Expand Down
1 change: 1 addition & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use vergen_git2::{Emitter, Git2Builder};

fn main() -> anyhow::Result<()> {
let git2 = Git2Builder::default()
.branch(true)
.describe(false, true, None)
.sha(false)
.build()?;
Expand Down
16 changes: 8 additions & 8 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pub mod cli_config;

use cli_config::ConfigCommands;
use clap::{Parser, Subcommand, Args};
use crate::{vars, FULL_VERSION};
use crate::FULL_VERSION;

const AFTER_HELP: &str = concat!(
"For documentation for this particular version go to following url\n",
Expand Down Expand Up @@ -30,7 +30,7 @@ pub struct Cli {
#[derive(Args, Debug, Clone, Default)]
pub struct CmdStartArgs {
/// Name of the new container (if not set a randomly generated name will be used)
#[arg(long, env = vars::CONTAINER)]
#[arg(long, env = crate::ENV_CONTAINER)]
pub name: Option<String>,

/// Path to directory which will be used as /etc/skel inside the container
Expand Down Expand Up @@ -94,7 +94,7 @@ pub struct CmdStartArgs {
pub env: Vec<String>,

/// Container image to use or @config
#[arg(env = vars::IMAGE, value_name = "IMAGE|@CONFIG")]
#[arg(env = crate::ENV_IMAGE, value_name = "IMAGE|@CONFIG")]
pub image: String,

/// Pass rest of args to engine verbatim
Expand Down Expand Up @@ -127,7 +127,7 @@ pub struct CmdShellArgs {
pub shell: Option<String>,

/// Name or the ID of the container
#[arg(value_name = "CONTAINER", default_value = "", env = vars::CONTAINER)]
#[arg(value_name = "CONTAINER", default_value = "", env = crate::ENV_CONTAINER)]
pub name: String,
}

Expand All @@ -140,7 +140,7 @@ pub struct CmdExecArgs {
pub shell: Option<String>,

/// Name or the ID of the container
#[arg(value_name = "CONTAINER", default_value = "", env = vars::CONTAINER)]
#[arg(value_name = "CONTAINER", default_value = "", env = crate::ENV_CONTAINER)]
pub name: String,

// NOTE command is required but last so that you can use name from environment
Expand All @@ -150,7 +150,7 @@ pub struct CmdExecArgs {

#[derive(Args, Debug, Clone)]
pub struct CmdExistsArgs {
#[arg(value_name = "CONTAINER", default_value = "", env = vars::CONTAINER)]
#[arg(value_name = "CONTAINER", default_value = "", env = crate::ENV_CONTAINER)]
pub name: String,
}

Expand All @@ -173,7 +173,7 @@ pub struct CmdLogsArgs {
#[arg(short, long)]
pub follow: bool,

#[arg(value_name = "CONTAINER", default_value = "", env = vars::CONTAINER)]
#[arg(value_name = "CONTAINER", default_value = "", env = crate::ENV_CONTAINER)]
pub name: String,
}

Expand All @@ -187,7 +187,7 @@ pub struct CmdKillArgs {
#[arg(short, long, default_value_t = 20)]
pub timeout: u32,

#[arg(value_name = "CONTAINER", default_value = "", env = vars::CONTAINER)]
#[arg(value_name = "CONTAINER", default_value = "", env = crate::ENV_CONTAINER)]
pub name: String,
}

Expand Down
1 change: 0 additions & 1 deletion src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,3 @@ pub use cmd_list::print_containers;
pub use cmd_logs::print_logs;
pub use cmd_kill::kill_container;
pub use cmd_init::container_init;

25 changes: 11 additions & 14 deletions src/commands/cmd_config/cmd_extract_config.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
use crate::ExitResult;
use crate::util::Engine;
use crate::prelude::*;
use crate::cli::cli_config::CmdConfigExtractArgs;
use crate::util::command_extensions::*;

pub fn extract_config(engine: Engine, dry_run: bool, cli_args: &CmdConfigExtractArgs) -> ExitResult {
pub fn extract_config(ctx: Context, cli_args: CmdConfigExtractArgs) -> Result<()> {
// allow dry run to run always
if !dry_run {
let cmd = Command::new(&engine.path)
if !ctx.dry_run {
let cmd = ctx.engine_command()
.args(["image", "exists", &cli_args.image])
.output()
.expect(crate::ENGINE_ERR_MSG);

if !cmd.status.success() {
eprintln!("Image {} does not exist", cli_args.image);

return Err(2);
return Err(anyhow!("Image {} does not exist", cli_args.image));
}
}

let mut cmd = Command::new(&engine.path);
let mut cmd = ctx.engine_command();
cmd.args([
"run", "--rm", "-it",
// basically just cat the file, should be pretty portable
Expand All @@ -27,8 +24,10 @@ pub fn extract_config(engine: Engine, dry_run: bool, cli_args: &CmdConfigExtract
"/config.toml"
]);

if dry_run {
cmd.print_escaped_cmd()
if ctx.dry_run {
cmd.print_escaped_cmd();

Ok(())
} else {
let output = cmd
.output()
Expand All @@ -40,9 +39,7 @@ pub fn extract_config(engine: Engine, dry_run: bool, cli_args: &CmdConfigExtract

Ok(())
} else {
eprintln!("Failed to extract config from image {}", cli_args.image);

Err(1)
return Err(anyhow!("Failed to extract config from image {}", cli_args.image));
}
}
}
21 changes: 7 additions & 14 deletions src/commands/cmd_config/cmd_inspect_config.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
use std::path::Path;

use crate::config::ConfigFile;
use crate::cli::cli_config::CmdConfigInspectArgs;
use crate::ExitResult;

pub fn inspect_config(cli_args: &CmdConfigInspectArgs) -> ExitResult {
match ConfigFile::load_from_file(&cli_args.path) {
Ok(x) => {
println!("{:#?}", x);
use crate::prelude::*;

Ok(())
},
Err(err) => {
// NOTE err is custom error so the message is already predefined
eprintln!("{}", err);
// TODO also try to find it as config name instead of literal path if prefixed @config
pub fn inspect_config(cli_args: CmdConfigInspectArgs) -> Result<()> {
println!("{:#?}", ConfigFile::load_from_file(Path::new(&cli_args.path))?);

Err(1)
}
}
Ok(())
}
16 changes: 6 additions & 10 deletions src/commands/cmd_config/cmd_options_config.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
use code_docs::DocumentedStruct;
use crate::config::Config;
use crate::util;
use crate::vars;
use crate::prelude::*;

pub fn show_config_options() {
pub fn show_config_options(ctx: Context) {
let docstring = Config::commented_fields()
.unwrap()
// replacing vec with array for people that dont know rust
.replace("Vec<", "Array<");

// TODO generate the example config with the serialize function instead of
// raw text so it is always up to date
println!(r#"ENV {appdir_env}: {appdir:?}
APP DIRECTORY: {appdir:?}
println!(r#"APP DIRECTORY (ENV {appdir_env}): {appdir:?}
CONFIG DIRECTORY: {cfgdir:?}
--- EXAMPLE CONFIG FILE ---
Expand All @@ -37,9 +34,8 @@ ports = [
--- CONFIG OPTIONS ---
"#,
appdir_env=vars::APP_DIR,
appdir=util::app_dir(),
cfgdir=util::config_dir(),
appdir_env=crate::ENV_APP_DIR,
appdir=ctx.app_dir,
cfgdir=ctx.config_dir(),
);
}

43 changes: 16 additions & 27 deletions src/commands/cmd_exec.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,34 @@
use crate::util::{self, Engine};
use crate::cli;
use crate::util::command_extensions::*;
use crate::ExitResult;
use crate::prelude::*;

pub fn container_exec(engine: Engine, dry_run: bool, mut cli_args: cli::CmdExecArgs) -> ExitResult {
pub fn container_exec(ctx: Context, mut cli_args: cli::CmdExecArgs) -> Result<()> {
// try to find container in current directory
if cli_args.name.is_empty() {
if let Some(containers) = util::find_containers_by_cwd(&engine) {
if let Some(containers) = ctx.get_cwd_container() {
if containers.is_empty() {
eprintln!("Could not find a running container in current directory");
return Err(1);
return Err(anyhow!("Could not find a running container in current directory"));
}

cli_args.name = containers.first().unwrap().clone();
}
} else if !dry_run && !util::container_exists(&engine, &cli_args.name) {
eprintln!("Container {:?} does not exist", &cli_args.name);
return Err(1);
} else if !ctx.dry_run && !ctx.engine_container_exists(&cli_args.name) {
return Err(anyhow!("Container {:?} does not exist", &cli_args.name));
}

// check if container is owned
let ws_dir = match util::get_container_ws(&engine, &cli_args.name) {
let ws_dir = match ctx.get_container_label(&cli_args.name, crate::CONTAINER_LABEL_CONTAINER_DIR) {
Some(x) => x,
// allow dry_run to work
None if dry_run => "/ws/dry_run".to_string(),
None => {
eprintln!("Container {:?} is not owned by {}", &cli_args.name, crate::APP_NAME);

return Err(1);
}
None if ctx.dry_run => "/ws/dry_run".to_string(),
None => return Err(anyhow!("Container {:?} is not owned by {}", &cli_args.name, crate::APP_NAME)),
};

let user = std::env::var("USER").expect("Unable to get USER from env var");

let mut cmd = Command::new(&engine.path);
let mut cmd = ctx.engine_command();
cmd.args(["exec", "-it"]);
cmd.args([
format!("--workdir={}", ws_dir),
format!("--user={}", user),
format!("--user={}", ctx.user),
format!("--env=TERM={}", std::env::var("TERM").unwrap_or("xterm".into())),
]);

Expand All @@ -57,13 +48,11 @@ pub fn container_exec(engine: Engine, dry_run: bool, mut cli_args: cli::CmdExecA
cmd.args(&cli_args.command);
}

if dry_run {
cmd.print_escaped_cmd()
if ctx.dry_run {
cmd.print_escaped_cmd();
} else {
cmd
.status()
.expect(crate::ENGINE_ERR_MSG)
.to_exitcode()
cmd.run_interactive()?;
}
}

Ok(())
}
22 changes: 12 additions & 10 deletions src/commands/cmd_exists.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
use crate::cli;
use crate::util::{self, Engine};
use crate::ExitResult;
use crate::prelude::*;

pub fn container_exists(engine: Engine, mut cli_args: cli::CmdExistsArgs) -> ExitResult {
pub fn container_exists(ctx: Context, mut cli_args: cli::CmdExistsArgs) -> Result<()> {
// try to find container in current directory
if cli_args.name.is_empty() {
if let Some(containers) = util::find_containers_by_cwd(&engine) {
// TODO this whole thing could be a function its used at least 3 times!
if let Some(containers) = ctx.get_cwd_container() {
if containers.is_empty() {
eprintln!("Could not find a running container in current directory");
return Err(1);
return Err(anyhow!("Could not find a running container in current directory"));
}

cli_args.name = containers.first().unwrap().clone();
}
}

match util::container_exists(&engine,&cli_args.name) {
use std::process::exit;

// TODO i am not sure if there is any problems with using exit here
match ctx.engine_container_exists(&cli_args.name) {
// give different exit code if the container exists but is not owned
true => match util::get_container_ws(&engine, &cli_args.name) {
true => match ctx.get_container_label(&cli_args.name, crate::CONTAINER_LABEL_CONTAINER_DIR) {
Some(_) => Ok(()),
None => Err(2),
None => exit(2),
},
false => Err(1),
false => exit(1),
}
}
Loading

0 comments on commit c14a5ca

Please sign in to comment.