diff --git a/apps/system/generic.py b/apps/system/generic.py index 182933f..9e4de51 100644 --- a/apps/system/generic.py +++ b/apps/system/generic.py @@ -27,18 +27,23 @@ def loggin(self): """ Loggin to the system. """ + i = 0 self.tty.wait_serial("login:", 600) - slp() - self.tty.writeln(self.username) - slp() - slp(10) # Some system would gives you "密码" instead of "Password"... Just sleep for a while. - slp() - self.tty.writeln(self.password) - slp() - self.tty.wait_serial(self.username) - slp() try: - self.tty.wait_serial("Current") + while i < 4: # May be failed to login, try again. + slp(10) + self.tty.writeln(self.username) + slp() + slp(10) # Some system would gives you "密码" instead of "Password"... Just sleep for a while. + slp() + self.tty.writeln(self.password) + slp() + i += 1 + self.tty.wait_serial("login:", 5) + except Exception as e: + pass + try: + self.tty.wait_serial("Current", 5) # Means the password is expired. slp() self.tty.writeln(self.password) diff --git a/apps/utils/maintain_img.py b/apps/utils/maintain_img.py index ac0d6d4..2814f5e 100644 --- a/apps/utils/maintain_img.py +++ b/apps/utils/maintain_img.py @@ -44,7 +44,7 @@ def extract_image(file: str) -> str: """ curr = os.getcwd() os.chdir(os.path.dirname(file)) - res = None + res = "".join(file.split(".")[:-1]) # check file type if not os.path.exists(file): os.chdir(curr) @@ -52,46 +52,45 @@ def extract_image(file: str) -> str: elif not os.path.isfile(file): os.chdir(curr) res = None - # For now support .tar, .tar.gz, .tar.bz2, .tar.xz, .zip + elif os.path.exists(res): + os.chdir(curr) + return res + # For now support .tar, .tar.gz, .tar.bz2, .tar.xz, .zip .zst + elif file.endswith(".zst"): + if not os.path.exists(file[:-4]): + os.system(f"zstd -d {file}") + res = file[:-4] elif file.endswith(".tar"): - if os.path.exists(file[:-4]): - res = file[:-4] - os.system(f"tar -xf {file}") + if not os.path.exists(file[:-4]): + os.system(f"tar -xf {file}") res = file[:-4] elif file.endswith(".tar.gz"): - if os.path.exists(file[:-7]): - res = file[:-7] - os.system(f"tar -xzf {file}") + if not os.path.exists(file[:-7]): + os.system(f"tar -xzf {file}") res = file[:-7] elif file.endswith(".tar.bz2"): - if os.path.exists(file[:-8]): - res = file[:-8] - os.system(f"tar -xjf {file}") + if not os.path.exists(file[:-8]): + os.system(f"tar -xjf {file}") res = file[:-8] elif file.endswith(".tar.xz"): - if os.path.exists(file[:-8]): - res = file[:-8] - os.system(f"tar -xJf {file}") + if not os.path.exists(file[:-8]): + os.system(f"tar -xJf {file}") res = file[:-8] elif file.endswith(".zip"): - if os.path.exists(file[:-4]): - res = file[:-4] - os.system(f"unzip {file}") + if not os.path.exists(file[:-4]): + os.system(f"unzip {file}") res = file[:-4] elif file.endswith(".xz"): - if os.path.exists(file[:-3]): - res = file[:-3] - os.system(f"unxz -k {file}") + if not os.path.exists(file[:-3]): + os.system(f"unxz -k {file}") res = file[:-3] elif file.endswith(".gz"): - if os.path.exists(file[:-3]): - res = file[:-3] - os.system(f"gunzip -k {file}") + if not os.path.exists(file[:-3]): + os.system(f"gunzip -k {file}") res = file[:-3] elif file.endswith(".bz2"): - if os.path.exists(file[:-4]): - res = file[:-4] - os.system(f"bunzip2 -k {file}") + if not os.path.exists(file[:-4]): + os.system(f"bunzip2 -k {file}") res = file[:-4] os.chdir(curr) return res diff --git a/src/exec/cli_exec.rs b/src/exec/cli_exec.rs index 0483acb..dedcc0b 100644 --- a/src/exec/cli_exec.rs +++ b/src/exec/cli_exec.rs @@ -5,7 +5,10 @@ use std::{ }; use crate::{ - cli::tty::{DynTty, Tty, WrapperTty}, consts::DURATION, err, impl_any, info, util::util::rand_string + cli::tty::{DynTty, Tty, WrapperTty}, + consts::DURATION, + err, impl_any, info, + util::util::rand_string, }; use super::cli_api::{CliTestApi, SudoCliTestApi}; @@ -73,7 +76,60 @@ impl CliTester { Ok(()) } - fn do_wait_serial(&mut self, expected: &str, timeout: u32, filter_echo_back: Option<&str>) -> Result> { + fn kmp_next(&self, target: &Vec) -> Vec { + let mut next = vec![0usize; target.len()]; + let mut i = 1; + let mut j = 0; + while i < target.len() - 1 { + if target[i] == target[j] { + next[i] = j + 1; + i += 1; + j += 1; + } else { + if j == 0 { + next[i] = 0; + i += 1; + } else { + j = next[j - 1] as usize; + } + } + } + next + } + + fn kmp_search(&self, content: &Vec, target: &Vec) -> Option { + let next = self.kmp_next(target); + let mut i = 0; + let mut j = 0; + let mut res = None; + while i < content.len() && j < target.len() { + if content[i] == target[j] { + if res.is_none() { + res = Some(i); + } + i += 1; + j += 1; + if j >= target.len() { + break; + } + } else { + if j == 0 { + i += 1; + } else { + j = next[j - 1]; + } + res = None; + } + } + res + } + + fn do_wait_serial( + &mut self, + expected: &str, + timeout: u32, + filter_echo_back: Option<&str>, + ) -> Result> { let begin = Instant::now(); let mut buf = Vec::new(); info!("Waiting for string {{{}}}", expected); @@ -84,10 +140,14 @@ impl CliTester { if let Some(filter) = filter_echo_back { self.filter_assert_echo(filter, &mut buf)?; } - let content = String::from_utf8(buf.clone()).unwrap_or_default(); - if content.contains(expected) { + // The reason we compare raw u8 is... What if the data is corrupted? + let target = expected.as_bytes(); + if let Some(pos) = self.kmp_search(&buf, &target.to_vec()) { info!("Matched string {{{}}}", expected); - break; + let res = buf.split_off(pos + target.len()); + let res = String::from_utf8(res)?; + buf.drain(0..pos + target.len()); + return Ok(res); } if begin.elapsed().as_secs() > timeout as u64 { err!( @@ -98,9 +158,6 @@ impl CliTester { return Err(Box::::from("Timeout")); } } - - let res = String::from_utf8(buf)?; - Ok(res) } } diff --git a/src/ui/cli_hooker.rs b/src/ui/cli_hooker.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/ui/mod.rs b/src/ui/mod.rs index e6f58cd..50fbd90 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -7,4 +7,5 @@ pub mod main; pub mod code_editor; -pub mod pyenv; \ No newline at end of file +pub mod pyenv; +pub mod terminal; \ No newline at end of file diff --git a/src/ui/terminal.rs b/src/ui/terminal.rs new file mode 100644 index 0000000..19b9e75 --- /dev/null +++ b/src/ui/terminal.rs @@ -0,0 +1,35 @@ +use eframe::egui::{Context, Id, Ui, Window}; + +use crate::impl_sub_window; + +use super::main::SubWindow; + +pub struct Terminal { + size: (u32, u32), +} + +impl Default for Terminal { + fn default() -> Self { + Terminal { size: (24, 80) } + } +} + +impl Terminal { + fn show(&mut self, ui: &mut Ui) { + ui.label("Terminal"); + } +} + +impl SubWindow for Terminal { + fn show(&mut self, ctx: &Context, title: &str, id: &Id, open: &mut bool) { + let window = Window::new(title) + .id(id.to_owned()) + .open(open) + .resizable([false, false]); + window.show(ctx, |ui| { + self.show(ui); + }); + } +} + +impl_sub_window!(Terminal, "Terminal");