1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
//! # Pacsea Crate Overview
//!
//! Pacsea bundles the core event loop, data pipelines, and UI helpers that power the
//! `pacsea` terminal application. Integration tests and downstream tooling can depend on this
//! crate to drive the runtime without going through the binary entrypoint.
//!
//! ## Why Pacsea?
//! > **TUI-first workflow:** Navigate Arch + AUR results with instant filtering, modal install
//! > previews, and keyboard-first ergonomics.
//! >
//! > **Complete ecosystem coverage:** Async workers query official repos, the AUR, mirrors, and
//! > Arch news so you can browse and act from one dashboard.
//! >
//! > **Aggressive caching & telemetry:** Persistent caches (`app::persist`) and ranked searches
//! > (`util::match_rank`) keep navigation snappy while structured tracing calls expose bottlenecks.
//!
//! ## Highlights
//! - TUI runtime (`app::runtime`) orchestrating async tasks, caches, and rendering.
//! - Modular subsystems for install flows, package index querying, and translation loading.
//! - Reusable helpers for theme paths, serialization, and UI composition.
//!
//! ## Crate Layout
//! - [`app`]: runtime, caches, and persistence glue for the interactive TUI.
//! - [`events`], [`logic`], [`install`]: event handling and command execution pipelines.
//! - [`index`], [`sources`]: Arch/AUR metadata fetchers plus enrichment.
//! - [`state`], [`theme`], [`ui`], [`util`]: configuration, rendering, and misc helpers.
//!
//! ## Quick Start
//! ```no_run
//! use pacsea::app;
//! use tracing_subscriber::EnvFilter;
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
//! let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("pacsea=info"));
//! tracing_subscriber::fmt()
//! .with_env_filter(filter)
//! .with_target(false)
//! .init();
//!
//! // Drive the full TUI runtime (set `true` for dry-run install previews)
//! app::run(false).await?;
//! Ok(())
//! }
//! ```
//!
//! See `src/main.rs` for the full CLI wiring (argument parsing, log file setup, and mode flags).
//!
//! ## Subsystem Map
//! | Module | Jump points | Responsibilities |
//! | --- | --- | --- |
//! | [`app`] | `app::run`, `app::sandbox_cache`, `app::services_cache` | Terminal runtime orchestration, cache persistence, sandbox + service metadata. |
//! | [`events`] | `events::search`, `events::recent` | Keyboard/mouse dispatchers that mutate `state::AppState`.
//! | [`logic`] | `logic::send_query`, `logic::deps::resolve_dependencies` | Core business rules for querying indices, ranking, and dependency analysis. |
//! | [`install`] | `install::command`, `install::spawn_install`, `install::spawn_remove_all` | Batch + single install orchestration, scan integrations, terminal helpers. |
//! | [`index`] | `index::load_from_disk`, `index::all_official`, `index::save_to_disk` | Persistent Arch index management and enrichment queues. |
//! | [`state`] | `state::AppState`, `state::types::PackageItem` | Shared UI/runtime data model and domain structs. |
//! | [`theme`] & [`ui`] | `theme::settings`, `ui::middle`, `ui::details` | Theme resolution, keymaps, and ratatui component tree. |
//! | [`util`] | `util::match_rank`, `util::repo_order`, `util::ts_to_date` | Pure helpers for scoring, formatting, and sorting.
//!
//! ## Testing Hooks
//! - `pacsea::global_test_mutex()` / `pacsea::global_test_mutex_lock()` serialize tests that mutate
//! global environment variables or touch shared caches.
//! - `state::test_mutex()` (private) is used inside state tests; prefer the crate-level guard for
//! integration suites that spawn the runtime.
//!
//! ```rust,ignore
//! #[tokio::test]
//! async fn installs_are_serialized() {
//! let _guard = pacsea::global_test_mutex_lock();
//! std::env::set_var("PATH", "/tmp/pacsea-tests/bin");
//! // run test body that mutates process globals
//! }
//! ```
//!
//! ## Common Tasks
//! **Kick off a search programmatically**
//! ```rust
//! use pacsea::logic::send_query;
//! use pacsea::state::{AppState, QueryInput};
//! use tokio::sync::mpsc;
//!
//! fn trigger_query(term: &str) {
//! let mut app = AppState {
//! input: term.to_string(),
//! ..Default::default()
//! };
//! let (tx, _rx) = mpsc::unbounded_channel::<QueryInput>();
//! send_query(&mut app, &tx);
//! }
//! ```
//!
//! **Inject a fake official index during tests**
//! ```rust
//! use pacsea::index::{load_from_disk, OfficialIndex, OfficialPkg};
//! use std::collections::HashMap;
//! use std::path::PathBuf;
//!
//! fn seed_index() {
//! let mut tmp = PathBuf::from(std::env::temp_dir());
//! tmp.push("pacsea_index_fixture.json");
//! let snapshot = OfficialIndex {
//! pkgs: vec![OfficialPkg {
//! name: "pacsea-demo".into(),
//! repo: "extra".into(),
//! arch: "x86_64".into(),
//! version: "1.0".into(),
//! description: "fixture".into(),
//! }],
//! name_to_idx: HashMap::new(), // Skipped during serialization
//! };
//! std::fs::write(&tmp, serde_json::to_string(&snapshot).unwrap()).unwrap();
//! load_from_disk(&tmp);
//! let _ = std::fs::remove_file(tmp);
//! }
//! ```
//!
//! The modules listed below link to detailed documentation for each subsystem.
// Backwards-compat shim: keep `crate::ui_helpers::*` working
pub use cratehelpers as ui_helpers;
static GLOBAL_TEST_MUTEX: OnceLock = new;
/// What: Provide a global mutex to serialize all tests that mutate PATH or other global environment variables.
///
/// Input: None.
/// Output: `&'static Mutex<()>` guard to synchronize tests touching global environment state.
///
/// Details:
/// - Lazily initializes a global `Mutex` via `OnceLock` for cross-test coordination.
/// - All tests that modify PATH, `WAYLAND_DISPLAY`, or other global environment variables should use this mutex.
/// - This ensures tests run serially even when --test-threads=1 is used, preventing race conditions.
/// - Handles poisoned mutexes gracefully by recovering from panics in previous tests.
/// What: Lock the global test mutex, handling poisoned mutexes gracefully.
///
/// Input: None.
/// Output: `MutexGuard<()>` that will be released when dropped.
///
/// Details:
/// - If the mutex is poisoned (from a previous test panic), recovers by acquiring the lock anyway.
/// - This allows tests to continue running even if a previous test panicked while holding the lock.