mirror of
https://codeberg.org/icewind/haze.git
synced 2026-06-03 17:14:08 +02:00
add formatting command
This commit is contained in:
parent
5f0551979a
commit
2627bb9427
6 changed files with 125 additions and 13 deletions
14
src/args.rs
14
src/args.rs
|
|
@ -42,6 +42,9 @@ pub enum HazeArgs {
|
||||||
Open {
|
Open {
|
||||||
filter: Option<String>,
|
filter: Option<String>,
|
||||||
},
|
},
|
||||||
|
Fmt {
|
||||||
|
path: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
|
@ -144,6 +147,13 @@ impl HazeArgs {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
HazeCommand::Open => Ok(HazeArgs::Open { filter }),
|
HazeCommand::Open => Ok(HazeArgs::Open { filter }),
|
||||||
|
HazeCommand::Fmt => {
|
||||||
|
let path = args
|
||||||
|
.next()
|
||||||
|
.map(S::into)
|
||||||
|
.ok_or_else(|| Report::msg("No path provided"))?;
|
||||||
|
Ok(HazeArgs::Fmt { path })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -160,6 +170,7 @@ pub enum HazeCommand {
|
||||||
Clean,
|
Clean,
|
||||||
Logs,
|
Logs,
|
||||||
Open,
|
Open,
|
||||||
|
Fmt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for HazeCommand {
|
impl FromStr for HazeCommand {
|
||||||
|
|
@ -177,6 +188,8 @@ impl FromStr for HazeCommand {
|
||||||
"clean" => Ok(HazeCommand::Clean),
|
"clean" => Ok(HazeCommand::Clean),
|
||||||
"logs" => Ok(HazeCommand::Logs),
|
"logs" => Ok(HazeCommand::Logs),
|
||||||
"open" => Ok(HazeCommand::Open),
|
"open" => Ok(HazeCommand::Open),
|
||||||
|
"fmt" => Ok(HazeCommand::Fmt),
|
||||||
|
"format" => Ok(HazeCommand::Fmt),
|
||||||
_ => Err(Report::msg(format!("Unknown command: {}", s))),
|
_ => Err(Report::msg(format!("Unknown command: {}", s))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -195,6 +208,7 @@ impl HazeCommand {
|
||||||
HazeCommand::Clean => false,
|
HazeCommand::Clean => false,
|
||||||
HazeCommand::Logs => true,
|
HazeCommand::Logs => true,
|
||||||
HazeCommand::Open => true,
|
HazeCommand::Open => true,
|
||||||
|
HazeCommand::Fmt => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
15
src/cloud.rs
15
src/cloud.rs
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::config::HazeConfig;
|
use crate::config::HazeConfig;
|
||||||
use crate::database::Database;
|
use crate::database::Database;
|
||||||
use crate::exec::{exec, exec_tty};
|
use crate::exec::{exec, exec_tty, ExitCode};
|
||||||
use crate::mapping::{default_mappings, Mapping};
|
use crate::mapping::{default_mappings, Mapping};
|
||||||
use crate::php::PhpVersion;
|
use crate::php::PhpVersion;
|
||||||
use crate::service::Service;
|
use crate::service::Service;
|
||||||
|
|
@ -15,7 +15,7 @@ use petname::petname;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::stdout;
|
use std::io::{stdout, Write};
|
||||||
use std::iter::Peekable;
|
use std::iter::Peekable;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
use std::os::unix::fs::MetadataExt;
|
use std::os::unix::fs::MetadataExt;
|
||||||
|
|
@ -302,7 +302,7 @@ impl Cloud {
|
||||||
docker: &mut Docker,
|
docker: &mut Docker,
|
||||||
cmd: Vec<S>,
|
cmd: Vec<S>,
|
||||||
tty: bool,
|
tty: bool,
|
||||||
) -> Result<i64> {
|
) -> Result<ExitCode> {
|
||||||
if tty {
|
if tty {
|
||||||
exec_tty(docker, &self.id, "haze", cmd, vec![]).await
|
exec_tty(docker, &self.id, "haze", cmd, vec![]).await
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -310,6 +310,15 @@ impl Cloud {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn exec_with_output<S: Into<String>>(
|
||||||
|
&self,
|
||||||
|
docker: &mut Docker,
|
||||||
|
cmd: Vec<S>,
|
||||||
|
output: Option<impl Write>,
|
||||||
|
) -> Result<ExitCode> {
|
||||||
|
exec(docker, &self.id, "haze", cmd, vec![], output).await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn list(
|
pub async fn list(
|
||||||
docker: &mut Docker,
|
docker: &mut Docker,
|
||||||
filter: Option<String>,
|
filter: Option<String>,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::exec::{exec, exec_tty};
|
use crate::exec::{exec, exec_tty, ExitCode};
|
||||||
use crate::image::pull_image;
|
use crate::image::pull_image;
|
||||||
use bollard::container::{Config, CreateContainerOptions, NetworkingConfig};
|
use bollard::container::{Config, CreateContainerOptions, NetworkingConfig};
|
||||||
use bollard::models::{EndpointSettings, HostConfig};
|
use bollard::models::{EndpointSettings, HostConfig};
|
||||||
|
|
@ -215,7 +215,7 @@ impl Database {
|
||||||
cloud_id: &str,
|
cloud_id: &str,
|
||||||
cmd: Vec<S>,
|
cmd: Vec<S>,
|
||||||
tty: bool,
|
tty: bool,
|
||||||
) -> Result<i64> {
|
) -> Result<ExitCode> {
|
||||||
let container = match self.family() {
|
let container = match self.family() {
|
||||||
DatabaseFamily::Sqlite => cloud_id.to_string(),
|
DatabaseFamily::Sqlite => cloud_id.to_string(),
|
||||||
_ => format!("{}-db", cloud_id.to_string()),
|
_ => format!("{}-db", cloud_id.to_string()),
|
||||||
|
|
@ -227,7 +227,7 @@ impl Database {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn exec(&self, docker: &mut Docker, cloud_id: &str, root: bool) -> Result<i64> {
|
pub async fn exec(&self, docker: &mut Docker, cloud_id: &str, root: bool) -> Result<ExitCode> {
|
||||||
match self.family() {
|
match self.family() {
|
||||||
DatabaseFamily::Sqlite => {
|
DatabaseFamily::Sqlite => {
|
||||||
exec_tty(
|
exec_tty(
|
||||||
|
|
|
||||||
38
src/exec.rs
38
src/exec.rs
|
|
@ -1,7 +1,7 @@
|
||||||
use bollard::container::LogsOptions;
|
use bollard::container::LogsOptions;
|
||||||
use bollard::exec::{CreateExecOptions, ResizeExecOptions, StartExecResults};
|
use bollard::exec::{CreateExecOptions, ResizeExecOptions, StartExecResults};
|
||||||
use bollard::Docker;
|
use bollard::Docker;
|
||||||
use color_eyre::{eyre::WrapErr, Result};
|
use color_eyre::{eyre::WrapErr, Report, Result};
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
use std::io::{stdout, Read, Write};
|
use std::io::{stdout, Read, Write};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
@ -17,7 +17,7 @@ pub async fn exec_tty<S1: AsRef<str>, S2: Into<String>>(
|
||||||
user: &str,
|
user: &str,
|
||||||
cmd: Vec<S2>,
|
cmd: Vec<S2>,
|
||||||
env: Vec<&str>,
|
env: Vec<&str>,
|
||||||
) -> Result<i64> {
|
) -> Result<ExitCode> {
|
||||||
let stdout = stdout();
|
let stdout = stdout();
|
||||||
|
|
||||||
if !is_tty(&stdout) {
|
if !is_tty(&stdout) {
|
||||||
|
|
@ -88,7 +88,8 @@ pub async fn exec_tty<S1: AsRef<str>, S2: Into<String>>(
|
||||||
.inspect_exec(&message.id)
|
.inspect_exec(&message.id)
|
||||||
.await?
|
.await?
|
||||||
.exit_code
|
.exit_code
|
||||||
.unwrap_or_default())
|
.unwrap_or_default()
|
||||||
|
.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn exec<S1: AsRef<str>, S2: Into<String>>(
|
pub async fn exec<S1: AsRef<str>, S2: Into<String>>(
|
||||||
|
|
@ -98,7 +99,7 @@ pub async fn exec<S1: AsRef<str>, S2: Into<String>>(
|
||||||
cmd: Vec<S2>,
|
cmd: Vec<S2>,
|
||||||
env: Vec<&str>,
|
env: Vec<&str>,
|
||||||
mut std_out: Option<impl Write>,
|
mut std_out: Option<impl Write>,
|
||||||
) -> Result<i64> {
|
) -> Result<ExitCode> {
|
||||||
let cmd = cmd.into_iter().map(S2::into).collect();
|
let cmd = cmd.into_iter().map(S2::into).collect();
|
||||||
let env = env.into_iter().map(String::from).collect();
|
let env = env.into_iter().map(String::from).collect();
|
||||||
let config = CreateExecOptions {
|
let config = CreateExecOptions {
|
||||||
|
|
@ -131,7 +132,8 @@ pub async fn exec<S1: AsRef<str>, S2: Into<String>>(
|
||||||
.inspect_exec(&message.id)
|
.inspect_exec(&message.id)
|
||||||
.await?
|
.await?
|
||||||
.exit_code
|
.exit_code
|
||||||
.unwrap_or_default())
|
.unwrap_or_default()
|
||||||
|
.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn container_logs(docker: &Docker, container: &str, count: usize) -> Result<Vec<String>> {
|
pub async fn container_logs(docker: &Docker, container: &str, count: usize) -> Result<Vec<String>> {
|
||||||
|
|
@ -150,3 +152,29 @@ pub async fn container_logs(docker: &Docker, container: &str, count: usize) -> R
|
||||||
}
|
}
|
||||||
Ok(logs)
|
Ok(logs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ExitCode(i64);
|
||||||
|
|
||||||
|
impl ExitCode {
|
||||||
|
pub fn is_ok(&self) -> Result<()> {
|
||||||
|
match self.0 {
|
||||||
|
0 => Ok(()),
|
||||||
|
code => Err(Report::msg(format!(
|
||||||
|
"Command failed with exit code {}",
|
||||||
|
code
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq<i64> for ExitCode {
|
||||||
|
fn eq(&self, other: &i64) -> bool {
|
||||||
|
&self.0 == other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i64> for ExitCode {
|
||||||
|
fn from(code: i64) -> Self {
|
||||||
|
ExitCode(code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
63
src/main.rs
63
src/main.rs
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::args::{ExecService, HazeArgs};
|
use crate::args::{ExecService, HazeArgs};
|
||||||
use crate::cloud::Cloud;
|
use crate::cloud::{Cloud, CloudOptions};
|
||||||
use crate::config::HazeConfig;
|
use crate::config::HazeConfig;
|
||||||
use crate::exec::container_logs;
|
use crate::exec::container_logs;
|
||||||
use crate::service::Service;
|
use crate::service::Service;
|
||||||
|
|
@ -203,6 +203,67 @@ async fn main() -> Result<()> {
|
||||||
cloud.exec(&mut docker, args, false).await?;
|
cloud.exec(&mut docker, args, false).await?;
|
||||||
cloud.destroy(&mut docker).await?;
|
cloud.destroy(&mut docker).await?;
|
||||||
}
|
}
|
||||||
|
HazeArgs::Fmt { path } => {
|
||||||
|
let cloud = Cloud::create(&mut docker, CloudOptions::default(), &config).await?;
|
||||||
|
let mut out_buffer = Vec::<u8>::with_capacity(1024);
|
||||||
|
println!("Waiting for servers to start");
|
||||||
|
cloud.wait_for_start(&mut docker).await?;
|
||||||
|
println!("Installing composer");
|
||||||
|
if let Err(e) = cloud
|
||||||
|
.exec_with_output(
|
||||||
|
&mut docker,
|
||||||
|
vec!["composer", "install"],
|
||||||
|
Some(&mut out_buffer),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.and_then(|c| c.is_ok())
|
||||||
|
{
|
||||||
|
eprintln!("{}", String::from_utf8_lossy(&out_buffer));
|
||||||
|
cloud.destroy(&mut docker).await?;
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
out_buffer.clear();
|
||||||
|
println!("Formatting");
|
||||||
|
if let Err(e) = cloud
|
||||||
|
.exec(
|
||||||
|
&mut docker,
|
||||||
|
vec!["composer", "run", "cs:fix", path.as_str()],
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
cloud.destroy(&mut docker).await?;
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
println!("Cleanup");
|
||||||
|
if let Err(e) = cloud
|
||||||
|
.exec_with_output(
|
||||||
|
&mut docker,
|
||||||
|
vec!["git", "clean", "-fd", "lib/composer"],
|
||||||
|
Some(&mut out_buffer),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.and_then(|c| c.is_ok())
|
||||||
|
{
|
||||||
|
eprintln!("{}", String::from_utf8_lossy(&out_buffer));
|
||||||
|
cloud.destroy(&mut docker).await?;
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
if let Err(e) = cloud
|
||||||
|
.exec_with_output(
|
||||||
|
&mut docker,
|
||||||
|
vec!["git", "checkout", "lib/composer"],
|
||||||
|
Some(&mut out_buffer),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.and_then(|c| c.is_ok())
|
||||||
|
{
|
||||||
|
eprintln!("{}", String::from_utf8_lossy(&out_buffer));
|
||||||
|
cloud.destroy(&mut docker).await?;
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
cloud.destroy(&mut docker).await?;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ pub fn default_mappings<'a>() -> impl IntoIterator<Item = Mapping<'a>> {
|
||||||
.file()
|
.file()
|
||||||
.read_only(),
|
.read_only(),
|
||||||
];
|
];
|
||||||
std::array::IntoIter::new(mappings)
|
IntoIterator::into_iter(mappings)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue