feat: set rust-version in Cargo.toml, closes #77

Update zigbuild docker run command to download latest rust version
This commit is contained in:
Jack Wills
2025-12-09 11:10:19 +00:00
parent 65d7970033
commit 0763a1024f
13 changed files with 50 additions and 62 deletions
+10 -2
View File
@@ -47,11 +47,19 @@ jobs:
- name: install cross - name: install cross
run: cargo install cross --git https://github.com/cross-rs/cross run: cargo install cross --git https://github.com/cross-rs/cross
# Build binary for arm MacOS using Docker Zigbuild
- name: build - name: build
if: matrix.target == 'aarch64-apple-darwin' if: matrix.target == 'aarch64-apple-darwin'
run: | run: |
docker run --rm -v $(pwd):/io -w /io ghcr.io/rust-cross/cargo-zigbuild cargo zigbuild --release --target aarch64-apple-darwin docker run --rm \
-v "$(pwd):/io" \
-w /io \
ghcr.io/rust-cross/cargo-zigbuild \
bash -ec '
rustup update stable
rustup default stable
rustup target add aarch64-apple-darwin
cargo zigbuild --release --target aarch64-apple-darwin
'
# Build all other targets using Cross # Build all other targets using Cross
- name: build - name: build
+1 -2
View File
@@ -7,8 +7,7 @@ description = "A simple tui to view & control docker containers"
repository = "https://github.com/mrjackwills/oxker" repository = "https://github.com/mrjackwills/oxker"
homepage = "https://github.com/mrjackwills/oxker" homepage = "https://github.com/mrjackwills/oxker"
license = "MIT" license = "MIT"
# This is stuck to whatever version cargo-zigbuild is using - https://github.com/rust-cross/cargo-zigbuild/blob/main/Dockerfile rust-version = "1.90.0"
rust-version = "1.87.0"
readme = "README.md" readme = "README.md"
keywords = ["docker", "tui", "tokio", "terminal", "podman"] keywords = ["docker", "tui", "tokio", "terminal", "podman"]
categories = ["command-line-utilities"] categories = ["command-line-utilities"]
+6 -2
View File
@@ -232,8 +232,12 @@ cross_build_x86_windows() {
# Build, using zig-build, for Apple silicon # Build, using zig-build, for Apple silicon
zig_build_aarch64_apple() { zig_build_aarch64_apple() {
# mkdir /workspace/oxker/target # mkdir /workspace/oxker/target
echo -e "${YELLOW}docker run --rm -v $(pwd):/io -w /io ghcr.io/rust-cross/cargo-zigbuild cargo zigbuild --release --target aarch64-apple-darwin${RESET}" echo -e "${YELLOW}docker run --rm -v $(pwd):/io -w /io ghcr.io/rust-cross/cargo-zigbuild bash -e -c 'rustup update stable && rustup default stable && rustup target add aarch64-apple-darwin && cargo zigbuild --release --target aarch64-apple-darwin${RESET}"
docker run --rm -v "$(pwd):/io" -w /io ghcr.io/rust-cross/cargo-zigbuild cargo zigbuild --release --target aarch64-apple-darwin
docker run --rm -v "$(pwd):/io" -w /io \
ghcr.io/rust-cross/cargo-zigbuild \
bash -ec 'rustup update stable && rustup default stable && rustup target add aarch64-apple-darwin && cargo zigbuild --release --target aarch64-apple-darwin'
if ask_yn "sudo chown $(pwd)/target"; then if ask_yn "sudo chown $(pwd)/target"; then
echo -e "${YELLOW}sudo chown -R vscode:vscode $(pwd)/target${RESET}" echo -e "${YELLOW}sudo chown -R vscode:vscode $(pwd)/target${RESET}"
sudo chown -R vscode:vscode "$(pwd)/target" sudo chown -R vscode:vscode "$(pwd)/target"
+4 -6
View File
@@ -689,12 +689,11 @@ impl Logs {
if let Some(new_index) = match sd { if let Some(new_index) = match sd {
ScrollDirection::Next => current_position.checked_add(1), ScrollDirection::Next => current_position.checked_add(1),
ScrollDirection::Previous => current_position.checked_sub(1), ScrollDirection::Previous => current_position.checked_sub(1),
} { }
if let Some(f) = self.search_results.get(new_index) { && let Some(f) = self.search_results.get(new_index) {
self.lines.state.select(Some(*f)); self.lines.state.select(Some(*f));
return Some(()); return Some(());
} }
}
} else { } else {
let range = match sd { let range = match sd {
ScrollDirection::Previous => (0..=current_selected).rev().collect::<Vec<_>>(), ScrollDirection::Previous => (0..=current_selected).rev().collect::<Vec<_>>(),
@@ -922,11 +921,10 @@ impl Logs {
/// Add a padding so one char will always be visilbe? /// Add a padding so one char will always be visilbe?
pub fn forward(&mut self, width: u16) { pub fn forward(&mut self, width: u16) {
let offset = usize::from(self.offset); let offset = usize::from(self.offset);
if self.horizontal_scroll_able(width) { if self.horizontal_scroll_able(width)
if self.adjusted_max_width > 0 && offset < self.adjusted_max_width { && self.adjusted_max_width > 0 && offset < self.adjusted_max_width {
self.offset = self.offset.saturating_add(1); self.offset = self.offset.saturating_add(1);
} }
}
} }
/// Reduce the char offset /// Reduce the char offset
+4 -6
View File
@@ -172,11 +172,10 @@ impl AppData {
} }
pub fn log_search_scroll(&mut self, np: &ScrollDirection) { pub fn log_search_scroll(&mut self, np: &ScrollDirection) {
if let Some(i) = self.get_mut_selected_container() { if let Some(i) = self.get_mut_selected_container()
if i.logs.search_scroll(np).is_some() { && i.logs.search_scroll(np).is_some() {
self.rerender.update_draw(); self.rerender.update_draw();
} }
}
} }
pub fn gen_log_search(&self) -> Option<LogSearch> { pub fn gen_log_search(&self) -> Option<LogSearch> {
@@ -340,14 +339,13 @@ impl AppData {
/// Sort containers based on a given header, if headings match, and already ascending, remove sorting /// Sort containers based on a given header, if headings match, and already ascending, remove sorting
pub fn set_sort_by_header(&mut self, selected_header: Header) { pub fn set_sort_by_header(&mut self, selected_header: Header) {
let mut output = Some((selected_header, SortedOrder::Asc)); let mut output = Some((selected_header, SortedOrder::Asc));
if let Some((current_header, order)) = self.get_sorted() { if let Some((current_header, order)) = self.get_sorted()
if current_header == selected_header { && current_header == selected_header {
match order { match order {
SortedOrder::Desc => output = None, SortedOrder::Desc => output = None,
SortedOrder::Asc => output = Some((selected_header, SortedOrder::Desc)), SortedOrder::Asc => output = Some((selected_header, SortedOrder::Desc)),
} }
} }
}
self.set_sorted(output); self.set_sorted(output);
} }
+4 -6
View File
@@ -158,8 +158,8 @@ impl From<Option<ConfigKeymap>> for Keymap {
|vec_str: Option<Vec<String>>, |vec_str: Option<Vec<String>>,
keymap_field: &mut (KeyCode, Option<KeyCode>), keymap_field: &mut (KeyCode, Option<KeyCode>),
keymap_clash: &mut HashSet<KeyCode>| { keymap_clash: &mut HashSet<KeyCode>| {
if let Some(vec_str) = vec_str { if let Some(vec_str) = vec_str
if let Some(vec_keycode) = Self::try_parse_keycode(&vec_str) { && let Some(vec_keycode) = Self::try_parse_keycode(&vec_str) {
if let Some(first) = vec_keycode.first() { if let Some(first) = vec_keycode.first() {
keymap_clash.insert(*first); keymap_clash.insert(*first);
counter += 1; counter += 1;
@@ -173,7 +173,6 @@ impl From<Option<ConfigKeymap>> for Keymap {
keymap_field.1 = None; keymap_field.1 = None;
} }
} }
}
}; };
if let Some(ck) = value { if let Some(ck) = value {
@@ -276,8 +275,8 @@ impl Keymap {
for key in input.iter().take(2) { for key in input.iter().take(2) {
if key.chars().count() == 1 { if key.chars().count() == 1 {
if let Some(first_char) = key.chars().next() { if let Some(first_char) = key.chars().next()
if let Some(first_char) = match first_char { && let Some(first_char) = match first_char {
x if x.is_ascii_alphabetic() || x.is_ascii_digit() => Some(first_char), x if x.is_ascii_alphabetic() || x.is_ascii_digit() => Some(first_char),
'/' | '\\' | ',' | '.' | '#' | '\'' | '[' | ']' | ';' | '=' | '-' => { '/' | '\\' | ',' | '.' | '#' | '\'' | '[' | ']' | ';' | '=' | '-' => {
Some(first_char) Some(first_char)
@@ -286,7 +285,6 @@ impl Keymap {
} { } {
output.push(KeyCode::Char(first_char)); output.push(KeyCode::Char(first_char));
} }
}
} else { } else {
let keycode = match key.to_lowercase().as_str() { let keycode = match key.to_lowercase().as_str() {
"f1" => Some(KeyCode::F(1)), "f1" => Some(KeyCode::F(1)),
+2 -3
View File
@@ -211,13 +211,12 @@ impl Config {
let args = Args::parse(); let args = Args::parse();
let config_from_cli = Self::from(&args); let config_from_cli = Self::from(&args);
if let Some(config_file) = &args.config_file { if let Some(config_file) = &args.config_file
if let Some(config_file) = && let Some(config_file) =
parse_config_file::ConfigFile::try_parse_from_file(config_file) parse_config_file::ConfigFile::try_parse_from_file(config_file)
{ {
return Self::from(config_file).merge_args(config_from_cli); return Self::from(config_file).merge_args(config_from_cli);
} }
}
if let Some(config_file) = parse_config_file::ConfigFile::try_parse(in_container) { if let Some(config_file) = parse_config_file::ConfigFile::try_parse(in_container) {
return Self::from(config_file).merge_args(config_from_cli); return Self::from(config_file).merge_args(config_from_cli);
+9 -19
View File
@@ -161,15 +161,15 @@ impl ExecMode {
let use_cli = app_data.lock().config.use_cli; let use_cli = app_data.lock().config.use_cli;
let container = app_data.lock().get_selected_container_id_state_name(); let container = app_data.lock().get_selected_container_id_state_name();
if let Some((id, state, _)) = container { if let Some((id, state, _)) = container
if [ && [
State::Running(RunningState::Healthy), State::Running(RunningState::Healthy),
State::Running(RunningState::Unhealthy), State::Running(RunningState::Unhealthy),
] ]
.contains(&state) .contains(&state)
{ {
if tty_readable() && !use_cli { if tty_readable() && !use_cli
if let Ok(exec) = docker && let Ok(exec) = docker
.create_exec( .create_exec(
id.get(), id.get(),
CreateExecOptions { CreateExecOptions {
@@ -180,34 +180,24 @@ impl ExecMode {
}, },
) )
.await .await
{ && let Ok(StartExecResults::Attached { mut output, .. }) =
if let Ok(StartExecResults::Attached { mut output, .. }) =
docker.start_exec(&exec.id, None).await docker.start_exec(&exec.id, None).await
{ && let Some(Ok(msg)) = output.next().await
if let Some(Ok(msg)) = output.next().await { && !msg.to_string().starts_with(OCI_ERROR) {
if !msg.to_string().starts_with(OCI_ERROR) {
return Some(Self::Internal(( return Some(Self::Internal((
Arc::new(id), Arc::new(id),
Arc::clone(docker), Arc::clone(docker),
))); )));
} }
}
}
}
}
if let Ok(output) = std::process::Command::new(command::DOCKER) if let Ok(output) = std::process::Command::new(command::DOCKER)
.args([command::EXEC, id.get(), command::PWD]) .args([command::EXEC, id.get(), command::PWD])
.output() .output()
{ && let Ok(output) = String::from_utf8(output.stdout)
if let Ok(output) = String::from_utf8(output.stdout) { && !output.starts_with(OCI_ERROR) {
if !output.starts_with(OCI_ERROR) {
return Some(Self::External(Arc::new(id))); return Some(Self::External(Arc::new(id)));
} }
}
}
} }
}
None None
} }
+2 -3
View File
@@ -178,8 +178,8 @@ impl InputHandler {
async fn save_logs(&self) -> Result<(), Box<dyn std::error::Error>> { async fn save_logs(&self) -> Result<(), Box<dyn std::error::Error>> {
let args = self.app_data.lock().config.clone(); let args = self.app_data.lock().config.clone();
let container = self.app_data.lock().get_selected_container_id_state_name(); let container = self.app_data.lock().get_selected_container_id_state_name();
if let Some((id, _, name)) = container { if let Some((id, _, name)) = container
if let Some(log_path) = args.save_dir { && let Some(log_path) = args.save_dir {
let (sx, rx) = tokio::sync::oneshot::channel(); let (sx, rx) = tokio::sync::oneshot::channel();
self.docker_tx.send(DockerMessage::Exec(sx)).await?; self.docker_tx.send(DockerMessage::Exec(sx)).await?;
@@ -230,7 +230,6 @@ impl InputHandler {
.set_info_box(&format!("saved to {}", path.display())); .set_info_box(&format!("saved to {}", path.display()));
} }
} }
}
Ok(()) Ok(())
} }
+2 -4
View File
@@ -1,4 +1,3 @@
#![allow(clippy::collapsible_if)]
// #![allow(unused)] // #![allow(unused)]
// Zigbuild is stuck on 1.87.0, which means Mac builds won't work when using collapsible ifs // Zigbuild is stuck on 1.87.0, which means Mac builds won't work when using collapsible ifs
@@ -64,8 +63,8 @@ async fn docker_init(
Docker::connect_with_socket(&host, 120, API_DEFAULT_VERSION) Docker::connect_with_socket(&host, 120, API_DEFAULT_VERSION)
}); });
if let Ok(docker) = connection { if let Ok(docker) = connection
if docker.ping().await.is_ok() { && docker.ping().await.is_ok() {
tokio::spawn(DockerData::start( tokio::spawn(DockerData::start(
Arc::clone(app_data), Arc::clone(app_data),
docker, docker,
@@ -75,7 +74,6 @@ async fn docker_init(
)); ));
return; return;
} }
}
app_data app_data
.lock() .lock()
.set_error(AppError::DockerConnect, gui_state, Status::DockerConnect); .set_error(AppError::DockerConnect, gui_state, Status::DockerConnect);
+2 -3
View File
@@ -39,15 +39,14 @@ fn gen_header<'a>(
fn gen_header_block<'a>(colors: AppColors, fd: &FrameData, header: Header) -> (Color, &'a str) { fn gen_header_block<'a>(colors: AppColors, fd: &FrameData, header: Header) -> (Color, &'a str) {
let mut color = colors.headers_bar.text; let mut color = colors.headers_bar.text;
let mut suffix = ""; let mut suffix = "";
if let Some((a, b)) = &fd.sorted_by { if let Some((a, b)) = &fd.sorted_by
if &header == a { && &header == a {
match b { match b {
SortedOrder::Asc => suffix = "", SortedOrder::Asc => suffix = "",
SortedOrder::Desc => suffix = "", SortedOrder::Desc => suffix = "",
} }
color = colors.headers_bar.text_selected; color = colors.headers_bar.text_selected;
} }
}
(color, suffix) (color, suffix)
} }
+2 -3
View File
@@ -103,13 +103,12 @@ fn generate_block<'a>(
.border_type(BorderType::Rounded) .border_type(BorderType::Rounded)
.title(ratatui::text::Line::from(title).left_aligned()); .title(ratatui::text::Line::from(title).left_aligned());
if panel == SelectablePanel::Logs { if panel == SelectablePanel::Logs
if let Some(x) = fd.scroll_title.as_ref() { && let Some(x) = fd.scroll_title.as_ref() {
block = block block = block
.title_bottom(x.to_owned()) .title_bottom(x.to_owned())
.title_alignment(ratatui::layout::Alignment::Right); .title_alignment(ratatui::layout::Alignment::Right);
} }
}
if !fd.status.contains(&Status::Filter) { if !fd.status.contains(&Status::Filter) {
if fd.selected_panel == panel { if fd.selected_panel == panel {
block = block.border_style(Style::default().fg(colors.borders.selected)); block = block.border_style(Style::default().fg(colors.borders.selected));
+2 -3
View File
@@ -237,8 +237,8 @@ impl Ui {
} }
} }
if crossterm::event::poll(POLL_RATE).unwrap_or(false) { if crossterm::event::poll(POLL_RATE).unwrap_or(false)
if let Ok(event) = event::read() { && let Ok(event) = event::read() {
if let Event::Key(key) = event { if let Event::Key(key) = event {
if key.kind == event::KeyEventKind::Press { if key.kind == event::KeyEventKind::Press {
self.input_tx self.input_tx
@@ -264,7 +264,6 @@ impl Ui {
self.gui_state.lock().set_screen_width(width); self.gui_state.lock().set_screen_width(width);
} }
} }
}
self.check_clear(); self.check_clear();
} }
Ok(()) Ok(())