diff --git a/.github/workflows/build_and_publish.yml b/.github/workflows/build_and_publish.yml new file mode 100644 index 0000000..b0cec86 --- /dev/null +++ b/.github/workflows/build_and_publish.yml @@ -0,0 +1,38 @@ +name: Build (tag and pull_request) and publish (tag) + +on: + push: + tags: + - v*.*.* + pull_request: +env: + CARGO_TERM_COLOR: always + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Build + run: docker-compose up + - name: Show dir + run: ls + - name: Upload Artifact + uses: actions/upload-artifact@v2.3.1 + with: + name: executables + path: | + **.AppImage + + publish: + needs: [build] + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/v') + steps: + - uses: actions/download-artifact@v2 + - uses: "marvinpinto/action-automatic-releases@v1.2.1" + with: + repo_token: "${{ secrets.GITHUB_TOKEN }}" + prerelease: false + files: | + **/*.AppImage diff --git a/src/main.rs b/src/main.rs index 0d80142..e73b335 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ use relm4::{factory::FactoryVec, RelmApp}; use ui::app::model::{AppModel, ToolboxContainer, ToolboxStatus}; mod ui; +mod toolbx; fn main() { let mut factory_vec = FactoryVec::new(); diff --git a/src/toolbx/mod.rs b/src/toolbx/mod.rs new file mode 100644 index 0000000..95af6ec --- /dev/null +++ b/src/toolbx/mod.rs @@ -0,0 +1,168 @@ +use std::{iter::zip, process::Command, sync::Arc, fmt::Result, string::ParseError}; + +#[derive(Debug, PartialEq)] +pub struct ToolbxContainer { + id: String, + name: String, + created: String, + status: String, + image: String, +} + +impl ToolbxContainer { + pub fn get_toolboxes() -> Vec { + let output = run_cmd_toolbx_list_containers(); + println!("{}", output); + parse_cmd_list_containers(output.as_str()) + } +} + +pub fn run_cmd_toolbx_list_containers() -> String { + let output = Command::new("toolbox") + .arg("list") + .arg("--containers") + .output() + .expect("Failed to execute command"); + + String::from_utf8_lossy(&output.stdout).to_string() +} + +#[test] +fn test_cmd_list_containers() { + // This requires toolbx to be installed + let toolbox_cmd_container_header = + "CONTAINER ID CONTAINER NAME CREATED STATUS IMAGE NAME"; + assert!(run_cmd_toolbx_list_containers().starts_with(toolbox_cmd_container_header)); +} + +fn tokenize_line_list_containers(line: &str) -> Vec { + let mut tokens = Vec::::new(); + let mut current_token = Vec::::new(); + + let mut whitespace_section = false; + + let mut iter = line.chars().peekable(); + while let Some(&c) = iter.peek() { + match (whitespace_section, c) { + (false, ' ') => { + iter.next(); + if Some(' ') == iter.peek().map(|x| x.clone()) { + whitespace_section = true; + } else { + current_token.push(c); + } + } + (true, ' ') => { + iter.next(); + } + (true, c) => { + whitespace_section = false; + tokens.push(current_token.into_iter().collect()); + current_token = Vec::new(); + current_token.push(c); + iter.next(); + } + (false, c) => { + current_token.push(c); + iter.next(); + } + } + } + tokens.push(current_token.into_iter().collect()); + + tokens +} + +#[test] +fn test_tokenize_line_list_containers() { + let toolbox_cmd_container_header = + "ae05203091ab rust 4 months ago running registry.fedoraproject.org/fedora-toolbox:35"; + + let target = vec![ + "ae05203091ab", + "rust", + "4 months ago", + "running", + "registry.fedoraproject.org/fedora-toolbox:35", + ]; + let result = tokenize_line_list_containers(toolbox_cmd_container_header); + assert_eq!(target, result); +} + +fn parse_line_list_containers(line: &str) -> ToolbxContainer { + let tokens = tokenize_line_list_containers(line); + if tokens.len() != 5 { + panic! {"Expected 5 tokens found {} in {:?}", tokens.len(), tokens}; + } + ToolbxContainer { + id: tokens[0].clone(), + name: tokens[1].clone(), + created: tokens[2].clone(), + status: tokens[3].clone(), + image: tokens[4].clone(), + } +} + +#[test] +fn test_parse_line_list_containers() { + let toolbox_cmd_container_header = + "ae05203091ab rust 4 months ago running registry.fedoraproject.org/fedora-toolbox:35"; + + let target = ToolbxContainer { + id: "ae05203091ab".to_string(), + name: "rust".to_string(), + created: "4 months ago".to_string(), + status: "running".to_string(), + image: "registry.fedoraproject.org/fedora-toolbox:35".to_string(), + }; + let result = parse_line_list_containers(toolbox_cmd_container_header); + assert_eq!(target, result); +} + +fn parse_cmd_list_containers(output: &str) -> Vec { + let lines = output.trim().split("\n").skip(1); + println!("{:?}", lines); + lines.map(parse_line_list_containers).collect() +} + +#[test] +fn test_parse_cmd_list_containers() { + // This requires toolbx to be installed + let toolbox_cmd_container_header = concat!( + "CONTAINER ID CONTAINER NAME CREATED STATUS IMAGE NAME\n", + "cee1002b5f0b fedora-toolbox-35 2 months ago exited registry.fedoraproject.org/fedora-toolbox:35\n", + "9b611313bf65 latex 4 months ago configured registry.fedoraproject.org/fedora-toolbox:35\n", + "ae05203091ab rust 4 months ago running registry.fedoraproject.org/fedora-toolbox:35\n" + ); + + let desired_result = vec![ + ToolbxContainer { + id: "cee1002b5f0b".to_string(), + name: "fedora-toolbox-35".to_string(), + created: "2 months ago".to_string(), + status: "exited".to_string(), + image: "registry.fedoraproject.org/fedora-toolbox:35".to_string(), + }, + ToolbxContainer { + id: "9b611313bf65".to_string(), + name: "latex".to_string(), + created: "4 months ago".to_string(), + status: "configured".to_string(), + image: "registry.fedoraproject.org/fedora-toolbox:35".to_string(), + }, + ToolbxContainer { + id: "ae05203091ab".to_string(), + name: "rust".to_string(), + created: "4 months ago".to_string(), + status: "running".to_string(), + image: "registry.fedoraproject.org/fedora-toolbox:35".to_string(), + }, + ]; + + for (result, desired) in zip( + parse_cmd_list_containers(toolbox_cmd_container_header).iter(), + desired_result.iter(), + ) { + assert_eq!(result, desired) + } +}