From 170a6f51c00ff3bc8d8670ee4de2e17535433d11 Mon Sep 17 00:00:00 2001 From: LGUG2Z Date: Thu, 5 Nov 2026 12:09:49 -0800 Subject: [PATCH] feat(catalog): index the komorebi source in this repository, not a checkout of each komorebi The recorder is a member of the repository it indexes: each flavor is built from the directory of its own daemon (komorebi-macos, komorebi-windows, komorebi-linux) and the shared crates that log. The statements of the container, workspace and monitor moved into komorebi-core, so the targets of the real log sample in the fixture are komorebi_core's. KOMOREBI_SRC and KOMOREBI_COMMIT replace the three KOMOREBI_*_SRC variables, for a build that is not in a checkout. --- komorebi-recorder/build.rs | 82 +++++++++++-------- komorebi-recorder/src/analysis/catalog.rs | 74 ++++++++--------- komorebi-recorder/src/analysis/code.rs | 4 +- komorebi-recorder/src/analysis/flavor/mod.rs | 19 +++++ komorebi-recorder/src/annotations.rs | 10 +-- komorebi-recorder/src/testkit.rs | 32 ++++---- komorebi-recorder/tests/code.rs | 13 +-- .../fixtures/komorebi_plaintext_sample.log | 30 +++---- komorebi-recorder/tests/trace.rs | 7 +- 9 files changed, 151 insertions(+), 120 deletions(-) diff --git a/komorebi-recorder/build.rs b/komorebi-recorder/build.rs index a9e700f2..1586d445 100644 --- a/komorebi-recorder/build.rs +++ b/komorebi-recorder/build.rs @@ -8,18 +8,18 @@ //! `komorebi-recorder code` can answer "which line wrote this?" and say when the answer may be //! about a different version of komorebi than the one that was recorded. //! -//! There is one catalog per flavor, because komorebi for Mac and komorebi for Windows are different -//! programs with different logs. Each is built from a checkout named by an environment variable: +//! There is one catalog per flavor, because komorebi for Windows, macOS and KDE Plasma are different +//! daemons with different logs. All of them are in this repository, so each is built from the +//! directories of its own daemon and of the crates it shares, in the checkout this crate is in: //! -//! | flavor | variable | when it is not set | -//! |---|---|---| -//! | macOS | `KOMOREBI_MAC_SRC` | an empty catalog, which says so | -//! | Windows | `KOMOREBI_WINDOWS_SRC` | an empty catalog, which says so | +//! | flavor | directories indexed | +//! |---|---| +//! | macOS | `komorebi-macos/src`, the shared crates | +//! | Windows | `komorebi-windows/src`, the shared crates | +//! | KDE | `komorebi-linux/src`, the shared crates | //! -//! The commit of each comes from git, or else from `KOMOREBI_MAC_COMMIT` / -//! `KOMOREBI_WINDOWS_COMMIT` for a build outside a checkout (nix). -//! -//! If a source is not there the catalog is empty and says so. +//! `KOMOREBI_SRC` names another checkout of the repository to index instead, and `KOMOREBI_COMMIT` the +//! commit of the source when it is not a git checkout (nix). The commit otherwise comes from git. //! //! The script also gives the Windows executables their icon, which Explorer reads from a resource in the file: see //! [`embed_icon`]. @@ -38,40 +38,47 @@ use syn::visit::Visit; struct Flavor { /// The name of its catalog in the generated code. name: &'static str, - /// The variable naming a checkout of it. - source_env: &'static str, - /// The variable giving the commit when the checkout is not a git repository. - commit_env: &'static [&'static str], /// The source trees to index: their directory under the checkout, and their Rust crate name. crates: &'static [(&'static str, &'static str)], } +/// The crates of every flavor that write log statements: the daemons call into them. +const SHARED: &[(&str, &str)] = &[ + ("komorebi-client/src", "komorebi_client"), + ("komorebi-layouts/src", "komorebi_layouts"), + ("crates/komorebi-core/src", "komorebi_core"), + ("crates/komorebi-transport/src", "komorebi_transport"), +]; + const FLAVORS: &[Flavor] = &[ Flavor { name: "MAC", - source_env: "KOMOREBI_MAC_SRC", - commit_env: &["KOMOREBI_MAC_COMMIT"], crates: &[ - ("komorebi/src", "komorebi"), - ("komorebi-client/src", "komorebi_client"), + ("komorebi-macos/src", "komorebi"), + SHARED[0], + SHARED[1], + SHARED[2], + SHARED[3], ], }, Flavor { name: "WINDOWS", - source_env: "KOMOREBI_WINDOWS_SRC", - commit_env: &["KOMOREBI_WINDOWS_COMMIT"], crates: &[ - ("komorebi/src", "komorebi"), - ("komorebi-layouts/src", "komorebi_layouts"), + ("komorebi-windows/src", "komorebi"), + SHARED[0], + SHARED[1], + SHARED[2], + SHARED[3], ], }, Flavor { name: "KDE", - source_env: "KOMOREBI_KDE_SRC", - commit_env: &["KOMOREBI_KDE_COMMIT"], crates: &[ - ("komorebi/src", "komorebi"), - ("komorebi-client/src", "komorebi_client"), + ("komorebi-linux/src", "komorebi"), + SHARED[0], + SHARED[1], + SHARED[2], + SHARED[3], ], }, ]; @@ -359,14 +366,18 @@ fn key(path: &Path, repo: &Path) -> String { /// The generated code for one flavor's catalog. fn index(flavor: &Flavor) -> String { - println!("cargo:rerun-if-env-changed={}", flavor.source_env); - for variable in flavor.commit_env { - println!("cargo:rerun-if-env-changed={variable}"); - } + println!("cargo:rerun-if-env-changed=KOMOREBI_SRC"); + println!("cargo:rerun-if-env-changed=KOMOREBI_COMMIT"); - let repo = env::var_os(flavor.source_env) + // this crate is a member of the repository it indexes + let repo = env::var_os("KOMOREBI_SRC") .map(PathBuf::from) - .filter(|path| !path.as_os_str().is_empty()); + .filter(|path| !path.as_os_str().is_empty()) + .or_else(|| { + env::var_os("CARGO_MANIFEST_DIR") + .map(PathBuf::from) + .and_then(|manifest| manifest.parent().map(Path::to_path_buf)) + }); let mut logs = Vec::new(); let mut spans = Vec::new(); @@ -432,10 +443,9 @@ fn index(flavor: &Flavor) -> String { .and_then(|repo| git(repo, &["rev-parse", "HEAD"])); let commit = from_git .or_else(|| { - flavor - .commit_env - .iter() - .find_map(|variable| env::var(variable).ok().filter(|hash| !hash.is_empty())) + env::var("KOMOREBI_COMMIT") + .ok() + .filter(|hash| !hash.is_empty()) }) .unwrap_or_default(); if let Some(repo) = &repo { diff --git a/komorebi-recorder/src/analysis/catalog.rs b/komorebi-recorder/src/analysis/catalog.rs index 70b543b1..13e04db6 100644 --- a/komorebi-recorder/src/analysis/catalog.rs +++ b/komorebi-recorder/src/analysis/catalog.rs @@ -19,18 +19,11 @@ //! programs with different logs, and [`of`] picks the one for the flavor a session recorded (see //! [`Analysis::catalog`](super::Analysis::catalog)): a session recorded on Windows is mapped to //! komorebi for Windows' source even when it is investigated on a Mac. Each is built from a -//! checkout of that komorebi named by an environment variable when the recorder is compiled: +//! source tree of this repository when the recorder is compiled: the daemon of the flavor and the crates +//! it shares (see `build.rs` for the directories). `KOMOREBI_SRC` and `KOMOREBI_COMMIT` index another checkout +//! instead, and name the commit when the source is not a git checkout (nix). //! -//! | flavor | checkout | its commit, outside a git checkout | directories indexed | -//! |---|---|---|---| -//! | [`Flavor::Macos`] | `KOMOREBI_MAC_SRC` | `KOMOREBI_MAC_COMMIT` | `komorebi/src`, `komorebi-client/src` | -//! | [`Flavor::Windows`] | `KOMOREBI_WINDOWS_SRC` | `KOMOREBI_WINDOWS_COMMIT` | `komorebi/src`, `komorebi-layouts/src` | -//! -//! `nix develop` sets all four. A flavor whose variable is not set (or whose checkout has no Rust -//! files in those directories) gets an **empty** catalog: nothing is found in it, -//! [`Catalog::is_empty`] is `true`, and [`skew`] tells the reader which variable to set. `build.rs` -//! prints a cargo warning if a checkout is named but nothing in it could be read, or if a file -//! fails to parse. +//! `build.rs` prints a cargo warning if nothing in the source could be read, or if a file fails to parse. //! //! What is indexed, for each Rust file of those directories: //! @@ -152,8 +145,8 @@ pub fn of(flavor: Flavor) -> &'static Catalog { impl Catalog { /// Returns the commit of the source that was indexed, or `None` if the checkout was not a git - /// repository and the build was not told the commit either (`KOMOREBI_MAC_COMMIT` or - /// `KOMOREBI_WINDOWS_COMMIT`), as is the case for an empty catalog. + /// repository and the build was not told the commit either (`KOMOREBI_COMMIT`), as is the case + /// for an empty catalog. #[must_use] pub fn commit(&self) -> Option<&'static str> { (!self.commit.is_empty()).then_some(self.commit) @@ -258,12 +251,12 @@ impl Statement { /// level: "INFO".to_string(), /// target: "komorebi::process_event".to_string(), /// template: "processing event: {} for process {} with notification {}".to_string(), - /// file: "komorebi/src/process_event.rs".to_string(), + /// file: "komorebi-macos/src/process_event.rs".to_string(), /// line: 120, /// function: "process_event".to_string(), /// owner: "WindowManager".to_string(), /// }; - /// assert_eq!(statement.location(), "komorebi/src/process_event.rs:120"); + /// assert_eq!(statement.location(), "komorebi-macos/src/process_event.rs:120"); /// assert_eq!(statement.qualified_function(), "WindowManager::process_event"); /// /// // outside any `impl`, the function stands alone @@ -381,12 +374,12 @@ impl Catalog { /// use komorebi_recorder::analysis::logparse::Level; /// /// let catalog = catalog::of(Flavor::Macos); - /// # if catalog.is_empty() { return; } // built without KOMOREBI_MAC_SRC: nothing is indexed + /// # if catalog.is_empty() { return; } // built without the source: nothing is indexed /// /// let found = catalog /// .find("komorebi::reaper", Level::Info, "reaping window: 4711") /// .expect("the reaper logs this"); - /// assert_eq!(found.statement.file, "komorebi/src/reaper.rs"); + /// assert_eq!(found.statement.file, "komorebi-macos/src/reaper.rs"); /// assert!(found.statement.template.starts_with("reaping window")); /// /// // no statement could have written this @@ -753,7 +746,7 @@ pub fn skew_between( /// `root` (see [`crate::annotations::default_code_root`]) to say which files differ. /// /// If the flavor's catalog is empty the warning is replaced by one saying that nothing is indexed -/// and which variable to build with (`KOMOREBI_MAC_SRC` or `KOMOREBI_WINDOWS_SRC`); the verdict is +/// and which variable to build with (`KOMOREBI_SRC`); the verdict is /// left as [`skew_between`] decided it. [`Analysis::skew`](super::Analysis::skew) calls this with /// the session's flavor and recorded versions. /// @@ -772,13 +765,8 @@ pub fn skew(flavor: Flavor, versions: &[KomorebiVersion], root: Option<&std::pat if catalog.is_empty() { skew.warning = Some(format!( "this build of komorebi-recorder has no source indexed for komorebi for {flavor}, so \ - log lines cannot be mapped to code; build it with {} pointing at a checkout of \ - komorebi for {flavor}", - match flavor { - Flavor::Macos => "KOMOREBI_MAC_SRC", - Flavor::Windows => "KOMOREBI_WINDOWS_SRC", - Flavor::Kde => "KOMOREBI_KDE_SRC", - } + log lines cannot be mapped to code; build it with KOMOREBI_SRC pointing at a checkout of \ + komorebi for {flavor}" )); } @@ -795,7 +783,13 @@ mod tests { } /// The directories of the Mac checkout that its catalog indexes. - const MAC_PATHS: &[&str] = &["komorebi/src", "komorebi-client/src"]; + const MAC_PATHS: &[&str] = &[ + "komorebi-macos/src", + "komorebi-client/src", + "komorebi-layouts/src", + "crates/komorebi-core/src", + "crates/komorebi-transport/src", + ]; fn commit() -> Option<&'static str> { mac().commit() @@ -856,7 +850,7 @@ mod tests { ) .expect("the header statement"); - assert_eq!(found.statement.file, "komorebi/src/process_event.rs"); + assert_eq!(found.statement.file, "komorebi-macos/src/process_event.rs"); assert_eq!(found.statement.function, "process_event"); assert_eq!(found.statement.owner, "WindowManager"); assert_eq!(found.confidence, Confidence::Likely); @@ -1001,7 +995,7 @@ mod tests { ); assert_eq!(skew.verdict, "same"); assert!(skew.warning.is_none()); - assert!(!skew.file_changed("komorebi/src/window.rs")); + assert!(!skew.file_changed("komorebi-macos/src/window.rs")); // but not if the source had uncommitted changes when indexed let dirty = skew_between( @@ -1032,15 +1026,17 @@ mod tests { .contains("cannot say how they differ") ); // when it cannot be told, nothing is vouched for - assert!(skew.file_changed("komorebi/src/window.rs")); + assert!(skew.file_changed("komorebi-macos/src/window.rs")); } #[test] fn an_older_commit_differs_in_exactly_the_files_git_says() { let Some(indexed) = commit() else { return }; // the commit before the latest change to komorebi's source - let Some(history) = git(&repo(), &["log", "-2", "--format=%H", "--", "komorebi/src"]) - else { + let Some(history) = git( + &repo(), + &["log", "-2", "--format=%H", "--", "komorebi-macos/src"], + ) else { return; }; let Some(older) = history.lines().nth(1) else { @@ -1062,8 +1058,11 @@ mod tests { older, indexed, "--", - "komorebi/src", + "komorebi-macos/src", "komorebi-client/src", + "komorebi-layouts/src", + "crates/komorebi-core/src", + "crates/komorebi-transport/src", ], ) .expect("git diff"); @@ -1079,7 +1078,7 @@ mod tests { for file in expected.lines() { assert!(skew.file_changed(file)); } - assert!(!skew.file_changed("komorebi/src/a_file_that_never_changed.rs")); + assert!(!skew.file_changed("komorebi-macos/src/a_file_that_never_changed.rs")); } fn rust_files(directory: &std::path::Path, found: &mut Vec) { @@ -1099,7 +1098,7 @@ mod tests { #[test] fn every_log_statement_in_komorebis_source_is_indexed() { crate::skip_without_komorebi_mac_source!(); - let root = crate::testkit::komorebi_mac_src().join("komorebi/src"); + let root = crate::testkit::komorebi_mac_src().join("komorebi-macos/src"); let mut files = Vec::new(); rust_files(&root, &mut files); @@ -1119,7 +1118,7 @@ mod tests { let indexed = mac() .entries .iter() - .filter(|entry| entry.file.starts_with("komorebi/src/")) + .filter(|entry| entry.file.starts_with("komorebi-macos/src/")) .count(); assert_eq!( indexed, in_source, @@ -1129,8 +1128,7 @@ mod tests { #[test] fn each_flavor_has_a_catalog_of_its_own_source() { - // the Windows catalog is built only when KOMOREBI_WINDOWS_SRC names a checkout; where it - // is, its statements are komorebi for Windows's, not the Mac's + // the Windows catalog is of the Windows daemon's source, not the Mac's let windows = of(Flavor::Windows); if windows.is_empty() { assert_eq!(windows.files_scanned(), 0); @@ -1167,7 +1165,7 @@ mod tests { let skew = skew(Flavor::Windows, &[], None); if of(Flavor::Windows).is_empty() { let warning = skew.warning.expect("a warning"); - assert!(warning.contains("KOMOREBI_WINDOWS_SRC"), "{warning}"); + assert!(warning.contains("KOMOREBI_SRC"), "{warning}"); } } } diff --git a/komorebi-recorder/src/analysis/code.rs b/komorebi-recorder/src/analysis/code.rs index 7b97d8d2..8baf1c77 100644 --- a/komorebi-recorder/src/analysis/code.rs +++ b/komorebi-recorder/src/analysis/code.rs @@ -292,13 +292,13 @@ impl Analysis { /// /// let (session, _) = SessionBuilder::new("doc-code-search").build(); /// let analysis = Analysis::open(&session.dir)?; - /// # if analysis.catalog().is_empty() { return Ok(()); } // built without KOMOREBI_MAC_SRC + /// # if analysis.catalog().is_empty() { return Ok(()); } // built without the source /// /// let found = analysis.code_search("Reaping WINDOW"); /// assert_eq!(found.about, "grep Reaping WINDOW"); /// assert!(found.lines.is_empty()); /// assert!(!found.statements.is_empty()); - /// assert!(found.statements.iter().any(|statement| statement.file == "komorebi/src/reaper.rs")); + /// assert!(found.statements.iter().any(|statement| statement.file == "komorebi-macos/src/reaper.rs")); /// # Ok::<(), Box>(()) /// ``` /// diff --git a/komorebi-recorder/src/analysis/flavor/mod.rs b/komorebi-recorder/src/analysis/flavor/mod.rs index 4f464fb6..a7ef8fc6 100644 --- a/komorebi-recorder/src/analysis/flavor/mod.rs +++ b/komorebi-recorder/src/analysis/flavor/mod.rs @@ -195,6 +195,25 @@ pub enum Flavor { } impl Flavor { + /// Returns the directory of this flavor's daemon source in the komorebi repository, which is + /// where [`Ref::Code`](crate::annotations::Ref::Code) paths for it start. + /// + /// # Example + /// + /// ```rust + /// use komorebi_recorder::analysis::flavor::Flavor; + /// + /// assert_eq!(Flavor::Macos.daemon_source(), "komorebi-macos/src"); + /// ``` + #[must_use] + pub const fn daemon_source(self) -> &'static str { + match self { + Flavor::Macos => "komorebi-macos/src", + Flavor::Windows => "komorebi-windows/src", + Flavor::Kde => "komorebi-linux/src", + } + } + /// Returns the flavor of the komorebi that runs on this machine: there is one per OS, and a /// recorder watches the one on its own host. /// diff --git a/komorebi-recorder/src/annotations.rs b/komorebi-recorder/src/annotations.rs index c7eb12f3..5e9be57f 100644 --- a/komorebi-recorder/src/annotations.rs +++ b/komorebi-recorder/src/annotations.rs @@ -1152,11 +1152,11 @@ pub fn delete(dir: &Path, id: &str) -> eyre::Result<()> { /// 1. the flavor's own environment variable: `KOMOREBI_MAC_SRC` for komorebi for Mac, /// `KOMOREBI_WINDOWS_SRC` for komorebi for Windows; /// 2. `KOMOREBI_SOURCE`, which serves either flavor; -/// 3. the checkout this recorder was built against, if it was built with one for this flavor (the -/// `KOMOREBI_MAC_ROOT` or `KOMOREBI_WINDOWS_ROOT` that its build script sets) and that -/// directory is still on disk. +/// 3. the checkout this recorder was built in (the `KOMOREBI_MAC_ROOT`, `KOMOREBI_WINDOWS_ROOT` or +/// `KOMOREBI_KDE_ROOT` that its build script sets), if that directory is still on disk. /// -/// The first candidate that has a `komorebi/src` directory is returned. A candidate that does not +/// The first candidate that has the flavor's daemon source directory (see +/// [`Flavor::daemon_source`]) is returned. A candidate that does not /// have one is skipped, not reported, so a variable that is set but wrong falls through to the /// next. `None` means no candidate qualified; [`validate_refs`] then cannot check [`Ref::Code`] /// and reports it in a warning. @@ -1187,7 +1187,7 @@ pub fn default_code_root(flavor: Flavor) -> Option { .filter_map(std::env::var_os) .map(PathBuf::from) .chain(built_from) - .find(|root| root.join("komorebi/src").is_dir()) + .find(|root| root.join(flavor.daemon_source()).is_dir()) } fn count_lines(path: &Path) -> std::io::Result { diff --git a/komorebi-recorder/src/testkit.rs b/komorebi-recorder/src/testkit.rs index ecc3aa1c..83349731 100644 --- a/komorebi-recorder/src/testkit.rs +++ b/komorebi-recorder/src/testkit.rs @@ -725,39 +725,37 @@ pub fn numbered_frame_index(bgra: &[u8], width: u32, height: u32) -> u32 { index } -/// The checkout of komorebi for Mac that the tests which read komorebi's source read it from. +/// The checkout of komorebi that the tests which read komorebi's source read it from. /// -/// That is the catalog and `code`. It is the checkout `KOMOREBI_MAC_SRC` names, which `nix develop` -/// sets to the revision pinned in `flake.lock`. +/// That is the catalog and `code`. It is the repository this crate is in, or the checkout +/// `KOMOREBI_SRC` names (nix builds the tests from a copy of the source). /// /// # Panics /// -/// Panics, naming the variable, when it is not set: those tests have nothing to check without a -/// tree. +/// Panics when the directory above the manifest cannot be found. #[must_use] pub fn komorebi_mac_src() -> PathBuf { - std::env::var_os("KOMOREBI_MAC_SRC") + std::env::var_os("KOMOREBI_SRC") .map(PathBuf::from) .filter(|path| !path.as_os_str().is_empty()) .unwrap_or_else(|| { - panic!( - "KOMOREBI_MAC_SRC is not set: it names the checkout of komorebi for Mac that these \ - tests read (`nix develop` sets it)" - ) + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .parent() + .expect("the repository above the crate") + .to_path_buf() }) } -/// Whether the tests that read komorebi for Mac's source can run: `KOMOREBI_MAC_SRC` names a -/// checkout, and this build indexed it (an empty catalog means it was built without one). +/// Whether the tests that read komorebi for Mac's source can run: this build indexed the source +/// (an empty catalog means it was built from a tree without it). /// -/// A machine that has neither (Windows, or a Mac outside `nix develop`) has nothing for those -/// tests to check, which is not a failure: they use +/// A build from a tree that has no komorebi source around it has nothing for those tests to +/// check, which is not a failure: they use /// [`skip_without_komorebi_mac_source!`](crate::skip_without_komorebi_mac_source) to say so and /// stop, as the tests that need `ffmpeg` do. #[must_use] pub fn komorebi_mac_source_available() -> bool { - std::env::var_os("KOMOREBI_MAC_SRC").is_some_and(|path| !path.is_empty()) - && !crate::analysis::catalog::of(crate::analysis::flavor::Flavor::Macos).is_empty() + !crate::analysis::catalog::of(crate::analysis::flavor::Flavor::Macos).is_empty() } /// Ends the test that uses it, saying why, on a machine that has no komorebi for Mac source to @@ -767,7 +765,7 @@ macro_rules! skip_without_komorebi_mac_source { () => { if !$crate::testkit::komorebi_mac_source_available() { eprintln!( - "skipped: KOMOREBI_MAC_SRC is not set, or this build was made without it \ + "skipped: this build indexed no komorebi source \ (`nix develop` sets it)" ); return; diff --git a/komorebi-recorder/tests/code.rs b/komorebi-recorder/tests/code.rs index 9c624594..43634f0b 100644 --- a/komorebi-recorder/tests/code.rs +++ b/komorebi-recorder/tests/code.rs @@ -35,7 +35,7 @@ fn session(name: &str, commit: Option<&str>) -> String { None, ) .log(2.0, "INFO", "process_event: komorebi::process_event: processing event: FocusChange for process 7 with notification AXApplicationActivated") - .log(2.1, "INFO", "process_event:focus_window{idx=0}: komorebi::container: focusing window") + .log(2.1, "INFO", "process_event:focus_window{idx=0}: komorebi_core::container: focusing window") .log(2.2, "INFO", "komorebi::reaper: reaping window: 4711") .log(2.25, "INFO", "komorebi::border_manager: invalidating border observer"); if let Some(commit) = commit { @@ -57,7 +57,7 @@ fn a_log_line_is_traced_to_the_statement_that_wrote_it() { assert_eq!(line["target"], "komorebi::reaper"); assert_eq!(line["message"], "reaping window: 4711"); let source = &line["source"]["statement"]; - assert_eq!(source["file"], "komorebi/src/reaper.rs"); + assert_eq!(source["file"], "komorebi-macos/src/reaper.rs"); assert!( source["template"] .as_str() @@ -149,7 +149,7 @@ fn git(args: &[&str]) -> Option { #[test] fn only_the_files_that_changed_since_the_recorded_commit_are_doubted() { komorebi_recorder::skip_without_komorebi_mac_source!(); - let Some(history) = git(&["log", "-2", "--format=%H", "--", "komorebi/src"]) else { + let Some(history) = git(&["log", "-2", "--format=%H", "--", "komorebi-macos/src"]) else { return; }; let Some(older) = history.lines().nth(1) else { @@ -164,8 +164,11 @@ fn only_the_files_that_changed_since_the_recorded_commit_are_doubted() { older, indexed, "--", - "komorebi/src", + "komorebi-macos/src", "komorebi-client/src", + "komorebi-layouts/src", + "crates/komorebi-core/src", + "crates/komorebi-transport/src", ]) else { return; }; @@ -237,7 +240,7 @@ fn statements_can_be_searched_by_their_text() { let statements = answer["data"]["statements"].as_array().expect("statements"); let in_reaper = statements .iter() - .filter(|statement| statement["file"] == "komorebi/src/reaper.rs") + .filter(|statement| statement["file"] == "komorebi-macos/src/reaper.rs") .count(); assert_eq!(in_reaper, 3, "{statements:#?}"); } diff --git a/komorebi-recorder/tests/fixtures/komorebi_plaintext_sample.log b/komorebi-recorder/tests/fixtures/komorebi_plaintext_sample.log index 91558e12..cb48dc0c 100644 --- a/komorebi-recorder/tests/fixtures/komorebi_plaintext_sample.log +++ b/komorebi-recorder/tests/fixtures/komorebi_plaintext_sample.log @@ -1,7 +1,7 @@ -2026-10-26T03:17:17.188982Z INFO process_event:focus_container{idx=0}: komorebi::workspace: focusing container +2026-10-26T03:17:17.188982Z INFO process_event:focus_container{idx=0}: komorebi_core::workspace: focusing container 2026-10-26T03:17:17.214014Z INFO process_event: komorebi::process_event: processing event: FocusChange for process 20934 with notification AXApplicationActivated -2026-10-26T03:17:17.216855Z INFO process_event:focus_window{idx=0}: komorebi::container: focusing window -2026-10-26T03:17:17.216865Z INFO process_event:focus_container{idx=0}: komorebi::workspace: focusing container +2026-10-26T03:17:17.216855Z INFO process_event:focus_window{idx=0}: komorebi_core::container: focusing window +2026-10-26T03:17:17.216865Z INFO process_event:focus_container{idx=0}: komorebi_core::workspace: focusing container 2026-10-26T03:37:19.703632Z INFO process_event: komorebi::process_event: processing event: FocusChange for process 681 with notification AXApplicationActivated 2026-10-26T03:37:19.781106Z ERROR process_event:update_focused_workspace{follow_focus=true trigger_focus=false}:update_focused_workspace:window_rect: komorebi::macos_api: failed to get window position: AXError::InvalidUIElement 2026-10-26T03:37:19.783788Z WARN process_event:update_focused_workspace{follow_focus=true trigger_focus=false}:update_focused_workspace: komorebi::workspace: failed to set window position: AXError::InvalidUIElement @@ -25,15 +25,15 @@ thread 'main' panicked at komorebi/src/example.rs:1:1: 2026-10-26T23:09:16.653486Z INFO process_event: komorebi::process_event: processing event: MoveEnd for process 96328 with notification AXWindowMoved 2026-10-26T23:09:16.664319Z INFO process_event: komorebi::process_event: processing event: MoveEnd for process 47907 with notification AXWindowMoved 2026-10-26T23:09:16.685293Z INFO process_event: komorebi::process_event: processing event: FocusChange for process 79469 with notification NSWorkspaceDidActivateApplicationNotification -2026-10-26T23:09:16.688494Z INFO process_event:focus_window{idx=0}: komorebi::container: focusing window -2026-10-26T23:09:16.688514Z INFO process_event:focus_container{idx=0}: komorebi::workspace: focusing container +2026-10-26T23:09:16.688494Z INFO process_event:focus_window{idx=0}: komorebi_core::container: focusing window +2026-10-26T23:09:16.688514Z INFO process_event:focus_container{idx=0}: komorebi_core::workspace: focusing container 2026-10-26T23:09:16.698081Z INFO process_event: komorebi::process_event: processing event: FocusChange for process 79469 with notification AXApplicationActivated -2026-10-26T23:09:16.700732Z INFO process_event:focus_window{idx=0}: komorebi::container: focusing window -2026-10-26T23:09:16.700745Z INFO process_event:focus_container{idx=0}: komorebi::workspace: focusing container +2026-10-26T23:09:16.700732Z INFO process_event:focus_window{idx=0}: komorebi_core::container: focusing window +2026-10-26T23:09:16.700745Z INFO process_event:focus_container{idx=0}: komorebi_core::workspace: focusing container 2026-10-26T23:09:17.733307Z INFO process_command: komorebi::process_command: processing command: FocusWorkspaceNumber 2026-10-26T23:09:17.733352Z INFO process_command:focus_workspace{idx=0}: komorebi::window_manager: focusing workspace -2026-10-26T23:09:17.733359Z INFO process_command:focus_workspace{idx=0}:focus_workspace{idx=0}: komorebi::monitor: focusing workspace -2026-10-26T23:09:17.756767Z INFO process_command:focus_workspace{idx=0}:focus_window{idx=0}: komorebi::container: focusing window +2026-10-26T23:09:17.733359Z INFO process_command:focus_workspace{idx=0}:focus_workspace{idx=0}: komorebi_core::monitor: focusing workspace +2026-10-26T23:09:17.756767Z INFO process_command:focus_workspace{idx=0}:focus_window{idx=0}: komorebi_core::container: focusing window 2026-10-26T23:09:17.887836Z INFO process_command: komorebi::process_command: processed command: FocusWorkspaceNumber 2026-10-26T23:09:17.889498Z INFO process_event: komorebi::process_event: processing event: MoveEnd for process 79469 with notification AXWindowMoved 2026-10-26T23:09:17.901710Z INFO komorebi::border_manager: invalidating border observer @@ -45,11 +45,11 @@ thread 'main' panicked at komorebi/src/example.rs:1:1: 2026-10-26T23:09:17.960135Z INFO process_event: komorebi::process_event: processing event: MoveEnd for process 1942 with notification AXWindowMoved 2026-10-26T23:09:17.969092Z INFO process_event: komorebi::process_event: processing event: MoveEnd for process 72441 with notification AXWindowMoved 2026-10-26T23:09:18.001875Z INFO process_event: komorebi::process_event: processing event: FocusChange for process 20934 with notification NSWorkspaceDidActivateApplicationNotification -2026-10-26T23:09:18.008861Z INFO process_event:focus_window{idx=0}: komorebi::container: focusing window -2026-10-26T23:09:18.008881Z INFO process_event:focus_container{idx=0}: komorebi::workspace: focusing container +2026-10-26T23:09:18.008861Z INFO process_event:focus_window{idx=0}: komorebi_core::container: focusing window +2026-10-26T23:09:18.008881Z INFO process_event:focus_container{idx=0}: komorebi_core::workspace: focusing container 2026-10-26T23:09:18.018616Z INFO process_event: komorebi::process_event: processing event: FocusChange for process 20934 with notification AXMainWindowChanged -2026-10-26T23:09:18.026372Z INFO process_event:focus_window{idx=0}: komorebi::container: focusing window -2026-10-26T23:09:18.026387Z INFO process_event:focus_container{idx=0}: komorebi::workspace: focusing container +2026-10-26T23:09:18.026372Z INFO process_event:focus_window{idx=0}: komorebi_core::container: focusing window +2026-10-26T23:09:18.026387Z INFO process_event:focus_container{idx=0}: komorebi_core::workspace: focusing container 2026-10-26T23:09:18.048765Z INFO process_event: komorebi::process_event: processing event: FocusChange for process 20934 with notification AXApplicationActivated -2026-10-26T23:09:18.052082Z INFO process_event:focus_window{idx=0}: komorebi::container: focusing window -2026-10-26T23:09:18.052094Z INFO process_event:focus_container{idx=0}: komorebi::workspace: focusing container +2026-10-26T23:09:18.052082Z INFO process_event:focus_window{idx=0}: komorebi_core::container: focusing window +2026-10-26T23:09:18.052094Z INFO process_event:focus_container{idx=0}: komorebi_core::workspace: focusing container diff --git a/komorebi-recorder/tests/trace.rs b/komorebi-recorder/tests/trace.rs index 2c4b240d..f85e00e4 100644 --- a/komorebi-recorder/tests/trace.rs +++ b/komorebi-recorder/tests/trace.rs @@ -85,7 +85,7 @@ fn session(name: &str) -> String { .log(3.5, "INFO", "komorebi::reaper: reaping window: 2") .log(3.6, "INFO", "komorebi::border_manager: invalidating border observer") .log(3.9, "INFO", "process_event: komorebi::process_event: processing event: FocusChange for process 7 with notification AXApplicationActivated") - .log(3.95, "INFO", "process_event:focus_container{idx=0}: komorebi::workspace: focusing container") + .log(3.95, "INFO", "process_event:focus_container{idx=0}: komorebi_core::workspace: focusing container") .log(5.9, "INFO", "process_event: komorebi::process_event: processing event: Show for process 7 with notification AXWindowCreated") .build(); session.dir.display().to_string() @@ -158,7 +158,10 @@ fn the_text_trace_reads_top_to_bottom() { assert!(handler < ambient && ambient < changed, "{text}"); assert!(text.contains("reaper (high)"), "{text}"); assert!(text.contains("evidence: log:2"), "{text}"); - assert!(text.contains("from komorebi/src/workspace.rs"), "{text}"); + assert!( + text.contains("from crates/komorebi-core/src/workspace.rs"), + "{text}" + ); } #[test]