Subject: [bug#76513] [PATCH rust-team v3 78/78] gnu: rust-typst-cli: Add bugfix patch.

From: Andrew Wong <[email-masked]>
Date: Sun, 2 Mar 2025 16:30:49 -0500

* gnu/packages/typst.scm (rust-typst-cli)[source]: Add bugfix patch from
upstream git.
* gnu/packages/patches/rust-typst-cli-fix-high-cpu-usage.patch: New file.

Change-Id: If055c0f8136a51f4a3a119b76dc04f5700b2b3e9
---
 .../rust-typst-cli-fix-high-cpu-usage.patch   | 97 +++++++++++++++++++
 gnu/packages/typst.scm                        |  8 +-
 2 files changed, 104 insertions(+), 1 deletion(-)
 create mode 100644 gnu/packages/patches/rust-typst-cli-fix-high-cpu-usage.patch

diff --git a/gnu/packages/patches/rust-typst-cli-fix-high-cpu-usage.patch b/gnu/packages/patches/rust-typst-cli-fix-high-cpu-usage.patch
new file mode 100644
index 0000000000..f3f1a88a6a
--- /dev/null
+++ b/gnu/packages/patches/rust-typst-cli-fix-high-cpu-usage.patch
@@ -0,0 +1,97 @@
+From acd3a5b7a5999d22fbf2da488744d564b2f3638e Mon Sep 17 00:00:00 2001
+From: aodenis <[email-masked]>
+Date: Tue, 25 Feb 2025 13:41:54 +0100
+Subject: [PATCH] Fix high CPU usage due to inotify watch triggering itself
+ (#5905)
+
+Co-authored-by: Laurenz <[email-masked]>
+---
+ src/watch.rs | 57 +++++++++++++++++++----------------
+ 1 file changed, 31 insertions(+), 26 deletions(-)
+
+diff --git a/src/watch.rs b/src/watch.rs
+index 91132fc3..cc727f0f 100644
+--- a/src/watch.rs
++++ b/src/watch.rs
+@@ -204,6 +204,10 @@ impl Watcher {
+                 let event = event
+                     .map_err(|err| eco_format!("failed to watch dependencies ({err})"))?;
+ 
++                if !is_relevant_event_kind(&event.kind) {
++                    continue;
++                }
++
+                 // Workaround for notify-rs' implicit unwatch on remove/rename
+                 // (triggered by some editors when saving files) with the
+                 // inotify backend. By keeping track of the potentially
+@@ -224,7 +228,17 @@ impl Watcher {
+                     }
+                 }
+ 
+-                relevant |= self.is_event_relevant(&event);
++                // Don't recompile because the output file changed.
++                // FIXME: This doesn't work properly for multifile image export.
++                if event
++                    .paths
++                    .iter()
++                    .all(|path| is_same_file(path, &self.output).unwrap_or(false))
++                {
++                    continue;
++                }
++
++                relevant = true;
+             }
+ 
+             // If we found a relevant event or if any of the missing files now
+@@ -234,32 +248,23 @@ impl Watcher {
+             }
+         }
+     }
++}
+ 
+-    /// Whether a watch event is relevant for compilation.
+-    fn is_event_relevant(&self, event: &notify::Event) -> bool {
+-        // Never recompile because the output file changed.
+-        if event
+-            .paths
+-            .iter()
+-            .all(|path| is_same_file(path, &self.output).unwrap_or(false))
+-        {
+-            return false;
+-        }
+-
+-        match &event.kind {
+-            notify::EventKind::Any => true,
+-            notify::EventKind::Access(_) => false,
+-            notify::EventKind::Create(_) => true,
+-            notify::EventKind::Modify(kind) => match kind {
+-                notify::event::ModifyKind::Any => true,
+-                notify::event::ModifyKind::Data(_) => true,
+-                notify::event::ModifyKind::Metadata(_) => false,
+-                notify::event::ModifyKind::Name(_) => true,
+-                notify::event::ModifyKind::Other => false,
+-            },
+-            notify::EventKind::Remove(_) => true,
+-            notify::EventKind::Other => false,
+-        }
++/// Whether a kind of watch event is relevant for compilation.
++fn is_relevant_event_kind(kind: &notify::EventKind) -> bool {
++    match kind {
++        notify::EventKind::Any => true,
++        notify::EventKind::Access(_) => false,
++        notify::EventKind::Create(_) => true,
++        notify::EventKind::Modify(kind) => match kind {
++            notify::event::ModifyKind::Any => true,
++            notify::event::ModifyKind::Data(_) => true,
++            notify::event::ModifyKind::Metadata(_) => false,
++            notify::event::ModifyKind::Name(_) => true,
++            notify::event::ModifyKind::Other => false,
++        },
++        notify::EventKind::Remove(_) => true,
++        notify::EventKind::Other => false,
+     }
+ }
+ 
+-- 
+2.48.1
+
diff --git a/gnu/packages/typst.scm b/gnu/packages/typst.scm
index 7deb5ef898..878ee7c433 100644
--- a/gnu/packages/typst.scm
+++ b/gnu/packages/typst.scm
@@ -101,7 +101,13 @@ (define-public rust-typst-cli
        (uri (crate-uri "typst-cli" version))
        (file-name (string-append name "-" version ".tar.gz"))
        (sha256
-        (base32 "09zfrcc5awycl4906r5qhzfmf9qc2jxb30z0iq7dizqkd6wl900i"))))
+        (base32 "09zfrcc5awycl4906r5qhzfmf9qc2jxb30z0iq7dizqkd6wl900i"))
+       (patches
+        ;; This patch should no longer apply after the next release.
+        ;; Please remove after its changes are integrated.
+        ;; (Version at time of writing: 0.13.0)
+        ;; (See: https://github.com/typst/typst/pull/5905)
+        (search-patches "rust-typst-cli-fix-high-cpu-usage.patch"))))
     (build-system cargo-build-system)
     (arguments
      `(#:cargo-inputs (("rust-chrono" ,rust-chrono-0.4)
-- 
2.48.1