Skip to content

Commit

Permalink
refactor + feat: use ron for config files
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanabx committed Apr 27, 2024
1 parent 7b94b62 commit aa86a34
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 142 deletions.
22 changes: 22 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ freedesktop-desktop-entry = "0.5.2"
freedesktop-icon-lookup = "0.1.3"
log = "0.4.21"
regex = "1.10.4"
ron = "0.8.1"
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.115"
walkdir = "2.5.0"
Expand Down
95 changes: 95 additions & 0 deletions src/container_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use std::path::Path;

use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
pub enum ContainerType {
Podman,
Docker,
Toolbox,
Unknown,
}

impl ContainerType {
pub fn not_supported(self) -> bool {
matches!(
self,
ContainerType::Docker | ContainerType::Podman | ContainerType::Unknown
)
}

pub fn format_copy(self, container_name: &str, from: &Path, to: &Path) -> String {
match self {
ContainerType::Toolbox => {
format!(
"podman container cp {}:{}/. {}/",
container_name,
from.to_str().unwrap(),
to.to_str().unwrap()
)
}
_ => "".to_string(), // TODO: Support more container types
}
}

pub fn format_exec(self, container_name: &str, command: &str) -> String {
match self {
ContainerType::Toolbox => {
format!("toolbox run -c {} {}", container_name, command)
}
_ => "".to_string(), // TODO: Support more container types
}
}

pub fn format_exec_regex_pattern(self) -> String {
match self {
ContainerType::Toolbox | ContainerType::Podman | ContainerType::Docker => {
r"(Exec=\s?)(.*)".to_string()
}
_ => "".to_string(),
}
}

pub fn format_desktop_exec(self, container_name: &str) -> String {
match self {
ContainerType::Toolbox => {
format!(r"Exec=toolbox run -c {} ${{2}}", container_name)
}
ContainerType::Podman => {
// TODO: Currently not always functional
format!(
r"Exec=sh -c 'podman container start {} && podman container exec {} ${{2}}'",
container_name, container_name
)
}
_ => "".to_string(), // TODO: Support more container types
}
}

pub fn format_name_regex_pattern(self) -> String {
match self {
ContainerType::Toolbox | ContainerType::Podman | ContainerType::Docker => {
r"(Name=\s?)(.*)".to_string()
}
_ => "".to_string(),
}
}

pub fn format_desktop_name(self, container_name: &str) -> String {
match self {
ContainerType::Toolbox => {
format!(r"Name=${{2}} ({})", container_name)
}
_ => "".to_string(), // TODO: Support more container types
}
}

pub fn format_start(self, container_name: &str) -> String {
match self {
ContainerType::Toolbox => {
format!("toolbox run -c {} echo 'Started'", container_name)
}
_ => "".to_string(), // TODO: Support more container types
}
}
}
172 changes: 42 additions & 130 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
use clap::Parser;
use server::ServerError;
use container_type::ContainerType;
use ron::de::SpannedError;
use serde::{Deserialize, Serialize};
use std::error::Error;
use std::fmt::Display;
use std::{env, fs, io};

use std::{fs::read_to_string, path::Path};

mod container_type;
mod desktop_entry;
mod server;

Expand All @@ -13,150 +18,66 @@ mod server;
struct Args {
#[arg(short, long, requires = "server", value_name = "CONFIG_PATH")]
/// [AS SERVER] Path to an alternate config for the program.
/// Default is $HOME/.config/container-desktop-entries/containers.conf
/// Default is $HOME/.config/container-desktop-entries/containers.ron
config: Option<String>,
}

#[derive(Debug, Clone, Copy)]
enum ContainerType {
Podman,
Docker,
Toolbox,
Unknown,
#[derive(Debug, Clone, Deserialize, Serialize)]
struct ContainerList {
pub containers: Vec<(String, ContainerType)>,
}

impl From<String> for ContainerType {
fn from(value: String) -> Self {
match value.as_str() {
"toolbox" => ContainerType::Toolbox,
"docker" => ContainerType::Docker,
"podman" => ContainerType::Podman,
_ => ContainerType::Unknown,
}
}
}
impl From<ContainerType> for String {
fn from(value: ContainerType) -> Self {
match value {
ContainerType::Toolbox => "toolbox".to_string(),
ContainerType::Docker => "docker".to_string(),
ContainerType::Podman => "podman".to_string(),
ContainerType::Unknown => "".to_string(),
}
}
#[derive(Debug)]
enum CDEError {
IO(io::Error),
NoEnv(std::env::VarError),
Ron(SpannedError),
}

impl ContainerType {
fn not_supported(self) -> bool {
matches!(
self,
ContainerType::Docker | ContainerType::Podman | ContainerType::Unknown
)
}

fn format_copy(self, container_name: &str, from: &Path, to: &Path) -> String {
match self {
ContainerType::Toolbox => {
format!(
"podman container cp {}:{}/. {}/",
container_name,
from.to_str().unwrap(),
to.to_str().unwrap()
)
}
_ => "".to_string(), // TODO: Support more container types
}
}

fn format_exec(self, container_name: &str, command: &str) -> String {
match self {
ContainerType::Toolbox => {
format!("toolbox run -c {} {}", container_name, command)
}
_ => "".to_string(), // TODO: Support more container types
}
impl Error for CDEError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
None
}

fn format_exec_regex_pattern(self) -> String {
match self {
ContainerType::Toolbox | ContainerType::Podman | ContainerType::Docker => {
r"(Exec=\s?)(.*)".to_string()
}
_ => "".to_string(),
}
fn description(&self) -> &str {
"description() is deprecated; use Display"
}

fn format_desktop_exec(self, container_name: &str) -> String {
match self {
ContainerType::Toolbox => {
format!(r"Exec=toolbox run -c {} ${{2}}", container_name)
}
ContainerType::Podman => {
// TODO: Currently not always functional
format!(
r"Exec=sh -c 'podman container start {} && podman container exec {} ${{2}}'",
container_name, container_name
)
}
_ => "".to_string(), // TODO: Support more container types
}
}

fn format_name_regex_pattern(self) -> String {
match self {
ContainerType::Toolbox | ContainerType::Podman | ContainerType::Docker => {
r"(Name=\s?)(.*)".to_string()
}
_ => "".to_string(),
}
}

fn format_desktop_name(self, container_name: &str) -> String {
match self {
ContainerType::Toolbox => {
format!(r"Name=${{2}} ({})", container_name)
}
_ => "".to_string(), // TODO: Support more container types
}
fn cause(&self) -> Option<&dyn Error> {
self.source()
}
}

fn format_start(self, container_name: &str) -> String {
impl Display for CDEError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ContainerType::Toolbox => {
format!("toolbox run -c {} echo 'Started'", container_name)
}
_ => "".to_string(), // TODO: Support more container types
Self::IO(e) => e.fmt(f),
Self::NoEnv(e) => e.fmt(f),
Self::Ron(e) => e.fmt(f),
}
}
}

#[derive(Debug)]
enum Error {
Server(ServerError),
IO(io::Error),
NoEnv(std::env::VarError),
}

impl From<ServerError> for Error {
fn from(value: ServerError) -> Self {
Error::Server(value)
impl From<io::Error> for CDEError {
fn from(value: io::Error) -> Self {
Self::IO(value)
}
}

impl From<io::Error> for Error {
fn from(value: io::Error) -> Self {
Error::IO(value)
impl From<std::env::VarError> for CDEError {
fn from(value: std::env::VarError) -> Self {
Self::NoEnv(value)
}
}

impl From<std::env::VarError> for Error {
fn from(value: std::env::VarError) -> Self {
Error::NoEnv(value)
impl From<SpannedError> for CDEError {
fn from(value: SpannedError) -> Self {
Self::Ron(value)
}
}

#[async_std::main]
async fn main() -> Result<(), Error> {
async fn main() -> Result<(), CDEError> {
env_logger::init();

if !cfg!(target_os = "linux") {
Expand All @@ -167,7 +88,7 @@ async fn main() -> Result<(), Error> {
let args = Args::parse();

let default_path_str = format!(
"{}/.config/container-desktop-entries/containers.conf",
"{}/.config/container-desktop-entries/containers.ron",
env::var("HOME")?
);
let conf_path = match args.config.as_ref() {
Expand All @@ -181,18 +102,9 @@ async fn main() -> Result<(), Error> {
}
_ => {}
}
log::info!("Running as server! Getting config at '{:?}'", conf_path);
let config_data = read_to_string(conf_path)?
.lines()
.map(|s| {
let ss = s
.split_once(" ")
.expect("Config invalid. make sure all lines are <<NAME>> <<TYPE>>");
(ss.0.to_string(), ContainerType::from(ss.1.to_string()))
})
.collect::<Vec<_>>();

server::server(config_data).await?;
let config_data: ContainerList = ron::from_str(&read_to_string(conf_path)?)?;

server::server(config_data).await;

Ok(())
}
Loading

0 comments on commit aa86a34

Please sign in to comment.