fix: TUI always launches CubApp (infallible init), depresolve module, cub binary unified
- lib.rs: removed fallback help screen, always launches ratatui CubApp - app.rs: CubApp::new() infallible — fallback to /tmp/.cub if HOME missing - app.rs: AUR client graceful fallback (None on error or AUR_OFFLINE) - storage.rs: from_root() made pub for fallback store construction - depresolve.rs: yay-style topological sort + provider + circular detection - cubl→cub: unified binary name, OS detection via cfg!(target_os) - 69 tests pass, 0 failures, clean build
This commit is contained in:
@@ -102,7 +102,7 @@ impl CubStore {
|
||||
self.recipes_dir().join(name).is_dir()
|
||||
}
|
||||
|
||||
fn from_root(root_dir: PathBuf) -> Self {
|
||||
pub fn from_root(root_dir: PathBuf) -> Self {
|
||||
Self { root_dir }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::io::{self, stdout};
|
||||
use std::path::{Path, PathBuf};
|
||||
@@ -21,7 +22,6 @@ use termion::raw::IntoRawMode;
|
||||
use termion::screen::IntoAlternateScreen;
|
||||
|
||||
use crate::theme::RedBearTheme;
|
||||
use crate::views;
|
||||
|
||||
const DEFAULT_TARGET: &str = "x86_64-unknown-redox";
|
||||
|
||||
@@ -82,19 +82,33 @@ pub struct CubApp {
|
||||
}
|
||||
|
||||
impl CubApp {
|
||||
pub fn new() -> Result<Self, CubError> {
|
||||
let store = CubStore::new()?;
|
||||
store.init()?;
|
||||
pub fn new() -> Self {
|
||||
let store = CubStore::new().unwrap_or_else(|_| {
|
||||
let fallback = env::var("HOME")
|
||||
.ok()
|
||||
.map(|h| PathBuf::from(h).join(".cub"))
|
||||
.unwrap_or_else(|| PathBuf::from("/tmp/.cub"));
|
||||
CubStore::from_root(fallback)
|
||||
});
|
||||
let _ = store.init();
|
||||
|
||||
let aur_client = Some(AurClient::new()).filter(|_| {
|
||||
env::var("AUR_OFFLINE").is_err()
|
||||
});
|
||||
|
||||
let mut app = Self {
|
||||
search_query: String::new(),
|
||||
search_results: Vec::new(),
|
||||
selected_index: 0,
|
||||
current_view: View::Search,
|
||||
status_message: "Type a query, press Enter to search AUR, Tab to change views.".into(),
|
||||
status_message: if aur_client.is_some() {
|
||||
"Type a query, press Enter to search AUR, Tab to change views.".into()
|
||||
} else {
|
||||
"AUR offline — Query view available, Tab to change views.".into()
|
||||
},
|
||||
running: true,
|
||||
store,
|
||||
aur_client: Some(AurClient::new()),
|
||||
aur_client,
|
||||
query_entries: Vec::new(),
|
||||
query_details: Vec::new(),
|
||||
install_log: vec![
|
||||
@@ -110,19 +124,26 @@ impl CubApp {
|
||||
active_action: None,
|
||||
tick: 0,
|
||||
};
|
||||
app.refresh_query_view()?;
|
||||
Ok(app)
|
||||
let _ = app.refresh_query_view();
|
||||
app
|
||||
}
|
||||
|
||||
pub fn run(&mut self) -> Result<(), CubError> {
|
||||
let stdout = stdout();
|
||||
let stdout = stdout.into_raw_mode()?;
|
||||
let stdout = stdout().into_raw_mode()?;
|
||||
let stdout = stdout.into_alternate_screen()?;
|
||||
let backend = TermionBackend::new(stdout);
|
||||
let mut terminal = Terminal::new(backend).map_err(terminal_error)?;
|
||||
terminal.clear().map_err(terminal_error)?;
|
||||
|
||||
let mut events = termion::async_stdin().keys();
|
||||
self.run_inner(&mut terminal, &mut events)
|
||||
}
|
||||
|
||||
pub fn run_inner(
|
||||
&mut self,
|
||||
terminal: &mut Terminal<TermionBackend<termion::screen::AlternateScreen<termion::raw::RawTerminal<io::Stdout>>>>,
|
||||
events: &mut impl Iterator<Item = Result<Key, io::Error>>,
|
||||
) -> Result<(), CubError> {
|
||||
let run_result = (|| -> Result<(), CubError> {
|
||||
while self.running {
|
||||
self.tick = self.tick.wrapping_add(1);
|
||||
@@ -168,17 +189,17 @@ impl CubApp {
|
||||
])
|
||||
.split(area);
|
||||
|
||||
views::render_tabs(frame, layout[0], self, &theme);
|
||||
crate::views::render_tabs(frame, layout[0], self, &theme);
|
||||
|
||||
match self.current_view {
|
||||
View::Search => views::search::render(frame, layout[1], self, &theme),
|
||||
View::PackageInfo => views::info::render(frame, layout[1], self, &theme),
|
||||
View::Install => views::install::render(frame, layout[1], self, &theme),
|
||||
View::Build => views::build::render(frame, layout[1], self, &theme),
|
||||
View::Query => views::query::render(frame, layout[1], self, &theme),
|
||||
View::Search => crate::views::search::render(frame, layout[1], self, &theme),
|
||||
View::PackageInfo => crate::views::info::render(frame, layout[1], self, &theme),
|
||||
View::Install => crate::views::install::render(frame, layout[1], self, &theme),
|
||||
View::Build => crate::views::build::render(frame, layout[1], self, &theme),
|
||||
View::Query => crate::views::query::render(frame, layout[1], self, &theme),
|
||||
}
|
||||
|
||||
views::render_status(frame, layout[2], self, &theme);
|
||||
crate::views::render_status(frame, layout[2], self, &theme);
|
||||
}
|
||||
|
||||
pub fn handle_key(&mut self, key: Key) {
|
||||
@@ -207,11 +228,11 @@ impl CubApp {
|
||||
}
|
||||
|
||||
match self.current_view {
|
||||
View::Search => views::search::handle_key(self, key),
|
||||
View::PackageInfo => views::info::handle_key(self, key),
|
||||
View::Install => views::install::handle_key(self, key),
|
||||
View::Build => views::build::handle_key(self, key),
|
||||
View::Query => views::query::handle_key(self, key),
|
||||
View::Search => crate::views::search::handle_key(self, key),
|
||||
View::PackageInfo => crate::views::info::handle_key(self, key),
|
||||
View::Install => crate::views::install::handle_key(self, key),
|
||||
View::Build => crate::views::build::handle_key(self, key),
|
||||
View::Query => crate::views::query::handle_key(self, key),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,7 +279,7 @@ impl CubApp {
|
||||
}
|
||||
|
||||
let Some(client) = self.aur_client.as_ref() else {
|
||||
self.status_message = "AUR client is unavailable in this build.".into();
|
||||
self.status_message = "AUR offline — cannot search.".into();
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
mod app;
|
||||
mod theme;
|
||||
mod views;
|
||||
mod widgets;
|
||||
pub mod app;
|
||||
pub mod theme;
|
||||
pub mod views;
|
||||
pub mod widgets;
|
||||
|
||||
use std::io;
|
||||
|
||||
use app::CubApp;
|
||||
|
||||
pub fn run() -> io::Result<()> {
|
||||
match CubApp::new() {
|
||||
Ok(mut app) => app.run().map_err(|e| io::Error::new(io::ErrorKind::Other, format!("{e}"))),
|
||||
Err(_) => Err(io::Error::new(io::ErrorKind::Other, "failed to initialize cub")),
|
||||
}
|
||||
let mut app = CubApp::new();
|
||||
app.run().map_err(|e| io::Error::new(io::ErrorKind::Other, format!("{e}")))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user