<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>ertius.org</title>
    <subtitle>Rob Weir&#39;s website</subtitle>
    <link rel="self" type="application/atom+xml" href="https://ertius.org/all.xml"/>
    <link rel="alternate" type="text/html" href="https://ertius.org/"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-09-26T00:00:00+00:00</updated>
    <id>https://ertius.org/all.xml</id>
    <entry xml:lang="en">
        <title>Emacs 31 on Debian Sid/Wayland</title>
        <published>2026-09-26T00:00:00+00:00</published>
        <updated>2026-09-26T00:00:00+00:00</updated>
        
        <author>
          <name>rweir@ertius.org (Rob Weir)</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://ertius.org/til/2026-09-26/"/><id>https://ertius.org/til/2026-09-26/</id>
        <content type="html" xml:base="https://ertius.org/til/2026-09-26/">&lt;p&gt;Emacs 31 is out and it&#39;s not yet in Sid, so let&#39;s build it from source!  First, fetch, configure and build it; fortunately Emacs 31 is fairly close to Emacs 30 in terms of build deps so there&#39;s not much to do:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellsession&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;❯&lt;/span&gt;&lt;span&gt; cd &lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;~&lt;/span&gt;&lt;span&gt;/src/thirdparty&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;❯&lt;/span&gt;&lt;span&gt; git clone https://github.com/emacs-mirror/emacs.git &lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-18&quot;&gt; cd&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; emacs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;❯&lt;/span&gt;&lt;span&gt; git checkout emacs-31.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;❯&lt;/span&gt;&lt;span&gt; run0 apt build-dep emacs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;❯&lt;/span&gt;&lt;span&gt; run0 apt install libgccjit-16-dev&lt;/span&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt;  #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt; need to get this manually, since emacs=30 depends on the version of gcc that was in trixie&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;❯&lt;/span&gt;&lt;span&gt; run0 apt install libwebkit2gtk-4.1-dev&lt;/span&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt;  #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt; needed for --with-xwidgets&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;❯&lt;/span&gt;&lt;span&gt; ./autogen.sh&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;❯&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt; CFLAGS&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;-O2 -march=native&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt; ./configure&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-with-native-compilation&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-with-tree-sitter&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-with-xwidgets&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-with-pgtk&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-with-file-notification=inotify&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-with-libsystemd&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-with-sound=alsa&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;❯&lt;/span&gt;&lt;span&gt; make -j &lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt;nproc&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A couple of things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;libgccjit-XX-dev&lt;/code&gt; needs to match the major version of GCC (&lt;code&gt;gcc --version&lt;/code&gt;) being used for this build, I&#39;m not sure why there isn&#39;t an unversioned &lt;code&gt;libgccjit-dev&lt;/code&gt; coupled to the &lt;code&gt;gcc&lt;/code&gt; package version&lt;/li&gt;
&lt;li&gt;on &lt;code&gt;amd64&lt;/code&gt; you want &lt;code&gt;-march=native&lt;/code&gt; to optimise for the current CPU, on &lt;code&gt;arm64&lt;/code&gt; you want &lt;code&gt;-mcpu=native&lt;/code&gt; (&lt;a rel=&quot;external&quot; href=&quot;https://maskray.me/blog/march-mcpu-mtune&quot;&gt;lots more details&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--with-pgtk&lt;/code&gt; is what lets it run under Wayland, the &#39;p&#39; stands for &lt;em&gt;pure&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To install it, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/ktetzlaff/src-emacs-on-debian.git&quot;&gt;I&#39;m going to use this package&lt;/a&gt;, which copies the files and installs a little &lt;code&gt;emacs-snapshot&lt;/code&gt; package to satisfy Debian dependencies:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellsession&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;❯&lt;/span&gt;&lt;span&gt; cd &lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;~&lt;/span&gt;&lt;span&gt;/src/thirdparty&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;❯&lt;/span&gt;&lt;span&gt; git clone https://github.com/ktetzlaff/src-emacs-on-debian.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;❯&lt;/span&gt;&lt;span&gt; cd emacs&lt;/span&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt;  #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt; the script is run from the *Emacs* source dir since it&amp;#39;s installing it&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;❯&lt;/span&gt;&lt;span&gt; run0 ../src-emacs-on-debian/restore-emacs&lt;/span&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt;  #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt; install it and set some symlinks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;❯&lt;/span&gt;&lt;span&gt; emacs -nw --debug-init&lt;/span&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt;  #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt; I like to run it from the command line once to let my config download and build things&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and here it is:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellsession&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;❯&lt;/span&gt;&lt;span&gt; apt-cache showpkg emacs-snapshot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;Package: emacs-snapshot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;Provides:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;2:1.0 - news-reader (= ) mail-reader (= ) info-browser (= ) emacsen (= ) editor (= )&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To load the provided &lt;code&gt;debian-init.el&lt;/code&gt;, &lt;code&gt;~/.emacs.d/init.el&lt;/code&gt; needs a small snippet near the top:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;emacs-lisp&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;eq&lt;/span&gt;&lt;span&gt; system-type &lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-7&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;gnu/linux&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;           (&lt;/span&gt;&lt;span class=&quot;z-l-1&quot;&gt;file-readable-p&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;/etc/os-release&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;           (&lt;/span&gt;&lt;span class=&quot;z-l-1&quot;&gt;with-temp-buffer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;             (&lt;/span&gt;&lt;span class=&quot;z-l-1&quot;&gt;insert-file-contents&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;/etc/os-release&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;             (&lt;/span&gt;&lt;span class=&quot;z-l-1&quot;&gt;goto-char&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;z-l-1&quot;&gt;point-min&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;             (&lt;/span&gt;&lt;span class=&quot;z-l-1&quot;&gt;re-search-forward&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;^ID=[&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-7&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;&amp;#39;]?debian[&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-7&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;&amp;#39;]?$&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; nil&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; t&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           invocation-directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;           (&lt;/span&gt;&lt;span class=&quot;z-l-1&quot;&gt;file-equal-p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;            (&lt;/span&gt;&lt;span class=&quot;z-l-1&quot;&gt;expand-file-name&lt;/span&gt;&lt;span&gt; invocation-name invocation-directory&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;            &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;/usr/local/bin/emacs&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;  (&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;(&lt;/span&gt;&lt;span&gt;debian-init &lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;z-l-1&quot;&gt;expand-file-name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;                      &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;~/src/thirdparty/src-emacs-on-debian/debian-init.el&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;    (&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;z-l-1&quot;&gt;file-exists-p&lt;/span&gt;&lt;span&gt; debian-init&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;      (&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;load&lt;/span&gt;&lt;span&gt; debian-init &lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-7&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;nomessage&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-7&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;nosuffix&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;My first attempt used &lt;code&gt;(string=)&lt;/code&gt; instead of &lt;code&gt;(file-equal-p)&lt;/code&gt;, which was buggy - the script also creates &lt;code&gt;/usr/bin/emacs-snapshot&lt;/code&gt; that points to &lt;code&gt;/usr/local/bin/emacs&lt;/code&gt;, and that won&#39;t match if it&#39;s invoked via the symlink.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>HP MicroServer Gen8 iLO and headless management</title>
        <published>2026-09-23T00:00:00+00:00</published>
        <updated>2026-09-23T00:00:00+00:00</updated>
        
        <author>
          <name>rweir@ertius.org (Rob Weir)</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://ertius.org/til/2026-09-23/"/><id>https://ertius.org/til/2026-09-23/</id>
        <content type="html" xml:base="https://ertius.org/til/2026-09-23/">&lt;p&gt;While tidying up a while ago, I re-found my old HP MicroServer Gen8.
I couldn&#39;t remember if I&#39;d even used it on the current iteration of my
home network or how I&#39;d felt about DHCP at the time, so step zero was
finding it on the network.  Normally this is not too much of a
challenge, since you can just plug in a monitor and keyboard, but I no
longer have anything with a VGA port and couldn&#39;t remember how the
Ethernet ports worked - it has three, a normal one, an iLO one and a
third port that can do both.&lt;/p&gt;
&lt;p&gt;After much dicking around, I learnt two things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I could only get the iLO web interface to actually work under
Firefox - Chrome and Safari are having nothing of it even after
clicking through all the security warnings&lt;/li&gt;
&lt;li&gt;other people still have them and care about them, including one
excellent hacker who wrote
&lt;a rel=&quot;external&quot; href=&quot;https://github.com/seveas/python-hpilo&quot;&gt;python-hpilo&lt;/a&gt;, a tool for
managing the iLO from the command line, including ... applying ten
years of updates with a few commands.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;They also helpfully have a big &lt;a rel=&quot;external&quot; href=&quot;https://seveas.github.io/python-hpilo/firmware.conf&quot;&gt;map of the various versions of the
firmware for the various versions of
iLO&lt;/a&gt; (HP
MicroServer Gen8 has iLO&lt;em&gt;4&lt;/em&gt;).  Bless your cotton socks, &lt;code&gt;@seveas&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Since the old iLO4 I had still required some sort of horrible &lt;code&gt;.NET&lt;/code&gt;
or &lt;code&gt;Java&lt;/code&gt; or &lt;code&gt;Java Web Start&lt;/code&gt; nonsense to access a console, I also
needed a plan for if I broke it and needed to reinstall it.
Fortunately I found
&lt;a rel=&quot;external&quot; href=&quot;https://github.com/philpagel/debian-headless&quot;&gt;debian-headless&lt;/a&gt;, a
tool for building a hacked up Debian installer image that pre-seeds
itself enough to get an SSH server running in the installer context,
so once you fish the IP out of your DHCP logs, you can ssh in.
Cheers, &lt;code&gt;@philpagel&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Overall, I&#39;ve been immensely spoiled by my recent foray into
enterprise gear &lt;a rel=&quot;external&quot; href=&quot;https://en.wikipedia.org/wiki/List_of_PowerEdge_servers#Generation_14&quot;&gt;that&#39;s only nine years
old&lt;/a&gt;,
since it has built-in HTML5 IPKVM and (at least theoretically) can
remote mount an installer ISO.&lt;/p&gt;
&lt;p&gt;Anyway, I thought I should update the 10 year old iLO firmware, so I
went up a &lt;code&gt;0.1&lt;/code&gt; at a time by incrementing the version in this command:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellsession&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;uv tool run --python 3.10 --from python-hpilo hpilo_cli 192.0.2.1 -l Administrator -i update_rib_firmware version=2.40&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Running this up to &lt;code&gt;2.81&lt;/code&gt; got me a copyright notice from 2019, and
hope against hope, the &lt;em&gt;Remote Console&lt;/em&gt; menu had a new option, &lt;em&gt;HTML5
Integrated Remote Console&lt;/em&gt; (added in
&lt;a rel=&quot;external&quot; href=&quot;https://internet-lab.ru/sites/internet-lab.ru/files/inline-files/HPE%20iLO%204%202.70%20Release%20Notes.pdf&quot;&gt;2.70&lt;/a&gt;
to be precise)!!!&lt;/p&gt;
&lt;p&gt;Shortly followed by a hugely helpful popup:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;This iLO is not licensed to use the Integrated Remote Console after server POST is complete.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Amazing stuff, adding a new feature &lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https://www.servethehome.com/hp-proliant-microserver-gen8-specs-leaked/&quot;&gt;SIX YEARS AFTER THE HARDWARE IS
RELEASED&lt;/a&gt;&lt;/strong&gt;
and putting it behind a paywall, absolutely amazing.&lt;/p&gt;
&lt;p&gt;Some other facts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the Windows .exe files named something like &lt;code&gt;cp053895.exe&lt;/code&gt; are
actually self-extracting ZIP files, and the files called something
like &lt;code&gt;CPQJ0613.684&lt;/code&gt; are the BIOS aka ROM files themselves, which you
can upload via iLO&#39;s web UI at &lt;code&gt;Administration -&amp;gt; Firmware&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;these .exe files are available on the web&lt;/li&gt;
&lt;li&gt;HP helpfully publishes SHA-256 checksums even for firmwares they have paywalled&lt;/li&gt;
&lt;li&gt;have a nice day&lt;/li&gt;
&lt;/ul&gt;

</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Special-Casing Added Files With diff-hl-mode</title>
        <published>2026-09-22T00:00:00+00:00</published>
        <updated>2026-09-22T00:00:00+00:00</updated>
        
        <author>
          <name>rweir@ertius.org (Rob Weir)</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://ertius.org/til/2026-09-22/"/><id>https://ertius.org/til/2026-09-22/</id>
        <content type="html" xml:base="https://ertius.org/til/2026-09-22/">&lt;p&gt;&lt;code&gt;diff-hl-mode&lt;/code&gt; is a very nice Emacs package - it marks added, deleted
and changed lines in the gutter.  However, it is a bit annoying when
you&#39;re in a newly staged and uncommitted file, since every line is
considered added, and with my usual themes that means marking every
line with a fairly bright green.  It doesn&#39;t seem to have a
configuration option for changing that behaviour, but because it&#39;s
Elisp, you can just advise a function:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;emacs-lisp&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-18&quot;&gt;defun&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt; rweir/diff-hl-ignore-added-files&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-3&quot;&gt;orig-fn&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; &amp;amp;rest&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-3&quot;&gt; args&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;Return no hunks for a newly added (staged, uncommitted) file.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;Without this, diff-hl marks every line of such a file as inserted.&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;  (&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;(&lt;/span&gt;&lt;span&gt;file &lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;(&lt;/span&gt;&lt;span&gt;diff-hl--buffer-file-name&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;    (&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;unless&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;and&lt;/span&gt;&lt;span&gt; file &lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;z-l-1&quot;&gt;vc-state&lt;/span&gt;&lt;span&gt; file&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-7&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;added&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;      (&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;apply&lt;/span&gt;&lt;span&gt; orig-fn args&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;z-l-1&quot;&gt;advice-add&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-7&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;diff-hl-changes&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-7&quot;&gt; :&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;around&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-7&quot;&gt; #&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-7&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;rweir/diff-hl-ignore-added-files&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once it&#39;s committed, the gutter will once again show modified lines.
A nice bit of Elisp design from the &lt;code&gt;diff-hl&lt;/code&gt; author -
&lt;code&gt;diff-hl-changes&lt;/code&gt; handles producing the changes for a single buffer,
so to ignore the changes for a buffer we simply wrap it and don&#39;t
call it.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Run Commands At Exact Git Refs</title>
        <published>2026-09-21T00:00:00+00:00</published>
        <updated>2026-09-21T00:00:00+00:00</updated>
        
        <author>
          <name>rweir@ertius.org (Rob Weir)</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://ertius.org/til/2026-09-21/"/><id>https://ertius.org/til/2026-09-21/</id>
        <content type="html" xml:base="https://ertius.org/til/2026-09-21/">&lt;p&gt;It is often very handy to be working on multiple things in a single
repository, and while &lt;code&gt;magit&lt;/code&gt; makes &lt;em&gt;unpicking&lt;/em&gt; local changes into
coherent commits easy, &lt;em&gt;testing&lt;/em&gt; those commits is kind of annoying.  My
primary use case for this was for testing changes in an Ansible tree -
often I have a lot of things in flight, but it&#39;s pretty important to
ensure that a commit is coherent.  Specifically: &lt;em&gt;the change refers to
a new file and the new file itself needs to end up in the same
commit&lt;/em&gt;.  Just running tests or &lt;code&gt;ansible-playbook --check --diff&lt;/code&gt;
doesn&#39;t help in that case, because all the files are in the tree, but
what you care about is whether they&#39;ll be committed together.&lt;/p&gt;
&lt;p&gt;So I wrote a little script, the gist of which is this:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt;#!&lt;/span&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt;/usr/bin/env bash&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-18&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;euo&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; pipefail&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-3&quot;&gt;main_repo&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; rev-parse&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-show-toplevel&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-3&quot;&gt;rel_dir&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; rev-parse&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-show-prefix&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-3&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;HOME&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;/.cache/run-at-worktrees&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-3&quot;&gt;mode_index&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-3&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;H&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;D&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;z-d-18&quot;&gt; [[&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-3&quot;&gt; $&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-3&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt; -gt&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; 0&lt;/span&gt;&lt;span class=&quot;z-d-18&quot;&gt; ]]&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;  case&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-3&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt; in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-3 z-d-18&quot;&gt;    -&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-18&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-18&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-18&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-18&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-18&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-18&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;   mode_index&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-18&quot;&gt; shift&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt; ;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-3 z-d-18&quot;&gt;    -&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-18&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-18&quot;&gt;        shift&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt; break&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt; ;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-3 z-d-18&quot;&gt;    -&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-7&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-18&quot;&gt;        echo&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;run-at: unknown flag: &lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-3&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt; &amp;gt;&amp;amp;2&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-18&quot;&gt; exit&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; 2&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt; ;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;    *)&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;         commit&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-3&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-18&quot;&gt; shift&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt; ;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;  esac&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;done&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;z-d-18&quot;&gt; [[&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-3&quot;&gt; $&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-3&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt; -eq&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; 0&lt;/span&gt;&lt;span class=&quot;z-d-18&quot;&gt; ]]&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt; then&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-18&quot;&gt;  echo&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;run-at: missing command&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt; &amp;gt;&amp;amp;2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-18&quot;&gt;  exit&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;fi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt; ((&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt; mode_index&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt; ))&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt; then&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-3&quot;&gt;  tree&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;main_repo&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; write-tree&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-3&quot;&gt;  sha&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;$(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-3&quot;&gt;    GIT_AUTHOR_DATE&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;@0 +0000&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt; GIT_COMMITTER_DATE&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;@0 +0000&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;    GIT_AUTHOR_NAME=run-at&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; GIT_AUTHOR_EMAIL=at@localhost&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-12&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;    GIT_COMMITTER_NAME=run-at&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; GIT_COMMITTER_EMAIL=at@localhost&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-12&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;    git&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;main_repo&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; commit-tree&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; HEAD&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-12&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;      -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;run-at index snapshot&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-3&quot;&gt;  label&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;index snapshot on top of &lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;main_repo&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; rev-parse&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-short&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; HEAD&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-3&quot;&gt;  sha&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;main_repo&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; rev-parse&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-verify&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;^{commit}&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-3&quot;&gt;  label&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;main_repo&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; log&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-format=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;%h %s&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;sha&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;fi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-3&quot;&gt;wt&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;sha&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt;mkdir&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;z-d-18&quot;&gt; [[&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt; !&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt; -d&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;wt&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-18&quot;&gt; ]]&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt; then&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt;  git&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;main_repo&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; worktree&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; add&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-detach&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;wt&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;sha&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;/dev/null&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;fi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-18&quot;&gt;echo&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;→ run-at: &lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;wt&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt; &amp;gt;&amp;amp;2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-18&quot;&gt;echo&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;  rev:  &lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;sha&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt; &amp;gt;&amp;amp;2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-18&quot;&gt;echo&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;  desc: &lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt; &amp;gt;&amp;amp;2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-3&quot;&gt;target_dir&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;wt&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;z-d-18&quot;&gt; [[&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt; -n&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;rel_dir&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-18&quot;&gt; ]]&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt; then&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-3&quot;&gt;  target_dir&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;wt&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;rel_dir&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;fi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;z-d-18&quot;&gt; [[&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt; !&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt; -d&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;target_dir&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-18&quot;&gt; ]]&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt; then&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-18&quot;&gt;  echo&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;run-at: target directory does not exist in selected revision: &lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;rel_dir&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;:-&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt; &amp;gt;&amp;amp;2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-18&quot;&gt;  exit&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;fi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-18&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;target_dir&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-18&quot;&gt;exec&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-3&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-3&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(the real version does some Ansible-specific stuff like symlinking the &lt;code&gt;venv&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;It&#39;s a lot of lines to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get a git commit id (or, if you pass &lt;code&gt;--index&lt;/code&gt;, create a temporary
commit from the staging area).  Either &lt;em&gt;must go&lt;/em&gt; before the &lt;code&gt;--&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Make a worktree in &lt;code&gt;~/.cache/run-at-worktrees&lt;/code&gt;, with the name based
on the commit.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd&lt;/code&gt; to the same relative directory (e.g. if I&#39;m in
&lt;code&gt;~/src/linux/drivers&lt;/code&gt;, ensure I end up in &lt;code&gt;./drivers&lt;/code&gt; in the worktree)&lt;/li&gt;
&lt;li&gt;Exec the provided command.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Setting the commit metadata - &lt;code&gt;GIT_AUTHOR_*&lt;/code&gt; and &lt;code&gt;GIT_COMMITTER_*&lt;/code&gt; -
to static values means the temporary commit&#39;s hash depends only on the
current commit + contents of the index, so we will reuse any previous
worktree that shared the same content (and &lt;code&gt;HEAD&lt;/code&gt;).  &lt;code&gt;commit-tree&lt;/code&gt;
ignores any configured &lt;code&gt;gpg&lt;/code&gt;/&lt;code&gt;ssh&lt;/code&gt; signing requirement, so it doesn&#39;t
require any creds and the commit id doesn&#39;t depend on keys or
timestamps.&lt;/p&gt;
&lt;p&gt;This is one of those things that in the past I might have considered
too slow to do, but on a 5-year-old Mac, running it on the Linux
kernel:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellsession&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;❯&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt; time&lt;/span&gt;&lt;span&gt; run-at -- pwd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;Preparing worktree (detached HEAD 9ecfb2f7287a)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;Updating files: 100% (94643/94643), done.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;→ run-at: /Users/rob/.cache/run-at-worktrees/9ecfb2f7287a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;  rev:  9ecfb2f7287a967b418ba69f10d45ead0d360593&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;  desc: 9ecfb2f7287a Merge tag &amp;#39;trace-ring-buffer-v7.2&amp;#39; of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;/Users/rob/.cache/run-at-worktrees/9ecfb2f7287a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;user=3.21s system=6.72s cpu=94% total=10.523&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since the worktree is named after the commit it&#39;s pointing at,
subsequent runs are ~instant:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellsession&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;❯&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt; time&lt;/span&gt;&lt;span&gt; run-at -- pwd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;→ run-at: /Users/rob/.cache/run-at-worktrees/9ecfb2f7287a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;  rev:  9ecfb2f7287a967b418ba69f10d45ead0d360593&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;  desc: 9ecfb2f7287a Merge tag &amp;#39;trace-ring-buffer-v7.2&amp;#39; of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;/Users/rob/.cache/run-at-worktrees/9ecfb2f7287a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;user=0.02s system=0.03s cpu=76% total=0.066&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;My code bases are much, much smaller than &lt;code&gt;linux.git&lt;/code&gt;, so that&#39;s plenty
fast enough for me for running tests or &lt;code&gt;uv run ansible-playbook --check --diff ...&lt;/code&gt;.  It is not fully hermetic, and any changes or
junk left in the worktree persist between runs, but it&#39;s turned
out to be very handy.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Trying To Make A Binary Cask With Homebrew</title>
        <published>2026-09-20T00:00:00+00:00</published>
        <updated>2026-09-20T00:00:00+00:00</updated>
        
        <author>
          <name>rweir@ertius.org (Rob Weir)</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://ertius.org/til/2026-09-20/"/><id>https://ertius.org/til/2026-09-20/</id>
        <content type="html" xml:base="https://ertius.org/til/2026-09-20/">&lt;p&gt;&lt;code&gt;homebrew&lt;/code&gt; is kinda weird compared to Debian and &lt;code&gt;apt&lt;/code&gt;, but it is quite thorough and means I can keep almost all my software on macOS up-to-date with just &lt;code&gt;brew upgrade&lt;/code&gt;.  For the things it didn&#39;t have, though, I&#39;d usually just install from source to &lt;code&gt;~/.local/bin&lt;/code&gt; and then leave it un-upgraded forever, which is not ideal.  I thought I&#39;d actually do it a bit more properly today, and, well, at least the &quot;copy these binary files&quot; part is not very complicated.&lt;/p&gt;
&lt;h2 id=&quot;jargon&quot;&gt;Jargon&lt;a class=&quot;anchor&quot; href=&quot;#jargon&quot; aria-label=&quot;Anchor link for: jargon&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;First, some jargon, since I can never remember what anything is in &lt;code&gt;brew&lt;/code&gt;-land:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;em&gt;formula&lt;/em&gt; is a package definition for installing open source software from source (or community-provided prebuilt binary &lt;em&gt;bottles&lt;/em&gt;) in the form of a Ruby file&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;cask&lt;/em&gt; is a package definition for installing a &lt;em&gt;binary&lt;/em&gt;, often a proprietary GUI app, which will be a &lt;code&gt;.rb&lt;/code&gt; file in the &lt;code&gt;Casks/&lt;/code&gt; directory of a &lt;em&gt;tap&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;tap&lt;/em&gt; is a Homebrew &quot;repository&quot;, somewhere it can download &lt;em&gt;formulas&lt;/em&gt; and &lt;em&gt;casks&lt;/em&gt; from (usually public &lt;code&gt;git&lt;/code&gt; repositories)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;Getting Started&lt;a class=&quot;anchor&quot; href=&quot;#getting-started&quot; aria-label=&quot;Anchor link for: getting-started&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I want to install &lt;code&gt;coop&lt;/code&gt;, from &lt;a rel=&quot;external&quot; href=&quot;https://github.com/trailofbits/coop&quot;&gt;trailofbits&lt;/a&gt;, a sandbox for running coding agents.  Since upstream already ship binaries, I thought I&#39;d try to use them, by creating a &lt;em&gt;cask&lt;/em&gt; that just downloaded them from GitHub and installed them.&lt;/p&gt;
&lt;p&gt;First I need a &lt;em&gt;tap&lt;/em&gt; to put it in.  The simplest way is to use GitHub, so let&#39;s do that:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt;brew&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; tap-new&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; rweir/homebrew-tap&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On &lt;code&gt;aarch64/macos&lt;/code&gt; at least, this creates a local git repository (owned by me) in &lt;code&gt;/opt/homebrew/Library/Taps/rweir/homebrew-tap&lt;/code&gt;.  Then create a matching repository on GitHub and push to it:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt;gh&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; repo&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; create&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;rweir/homebrew-tap&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-12&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;    -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-push&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-public&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-12&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;    -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-source&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt;brew&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-repository&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;rweir/homebrew-tap&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you have a personal &lt;code&gt;tap&lt;/code&gt;, which you and anyone else can tell their local &lt;code&gt;brew&lt;/code&gt; to use:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt;brew&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; tap&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; rweir/tap&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;brew&lt;/code&gt; implicitly strips the &lt;code&gt;homebrew-&lt;/code&gt; from the repository name, so GitHub repo name &lt;code&gt;rweir/homebrew-tap&lt;/code&gt; maps to &lt;code&gt;brew tap&lt;/code&gt; argument &lt;code&gt;rweir/tap&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So, I ask &lt;code&gt;brew&lt;/code&gt; to create the basic cask file for me to fill in:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt;brew&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; create&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-cask&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-12&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;    https://github.com/trailofbits/coop/releases/download/v0.6.0/coop-v0.6.0-aarch64-apple-darwin.tar.gz&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-12&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;    -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-tap&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; rweir/homebrew-tap&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-12&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;    -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-set-name&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; coop&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then &lt;a rel=&quot;external&quot; href=&quot;https://github.com/rweir/homebrew-tap/blob/main/Casks/coop.rb&quot;&gt;just draw the rest of the owl&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cask &lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;coop&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  version &lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;0.6.0&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  sha256 &lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;2eb045bbbb24e25c995500f93146eea5ee866595f9042ad441cb930d7ada3ed6&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  depends_on &lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;arch&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-7&quot;&gt; :&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;arm64&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  depends_on &lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;macos&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt;  #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt; Where to download the binary from&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  url &lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;https://github.com/trailofbits/coop/releases/download/v&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-7&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-7&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;/coop-v&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-7&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-7&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;-aarch64-apple-darwin.tar.gz&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  name &lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;coop&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  desc &lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;Isolated VM environment for running Claude Code and Codex&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  homepage &lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;https://github.com/trailofbits/coop&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt;  #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt; Use the templated `url` field above to find other versions&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  livecheck &lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    url &lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;url&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-16&quot;&gt;    regex&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-18&quot;&gt;^v?&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;z-l-2 z-l-b z-d-12&quot;&gt;\d&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-18&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-18&quot;&gt;?:&lt;/span&gt;&lt;span class=&quot;z-l-2 z-l-b z-d-12&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;z-l-2 z-l-b z-d-12&quot;&gt;\d&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-18&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-18&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-18&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;/i&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt;  #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt; binaries are in a subdirectory inside the tarball, `brew` will use&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt;  #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-d-5 z-d-i&quot;&gt; the basename as the target&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  binary &lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;coop-v&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-7&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-7&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;-aarch64-apple-darwin/coop&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  binary &lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;coop-v&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-7&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-7&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;-aarch64-apple-darwin/coop-proxy&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;keeping-it-up-to-date&quot;&gt;Keeping It Up To Date&lt;a class=&quot;anchor&quot; href=&quot;#keeping-it-up-to-date&quot; aria-label=&quot;Anchor link for: keeping-it-up-to-date&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;brew&lt;/code&gt; includes tooling to check for upstream updates:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellsession&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt; HOMEBREW_NO_AUTO_UPDATE&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-4&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt; brew&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; livecheck&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-cask&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; rweir/tap/coop&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;coop: 0.6.0 ==&amp;gt; 0.6.0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When there&#39;s a new version, I can make and then merge a PR to update &lt;code&gt;version&lt;/code&gt; and &lt;code&gt;sha256&lt;/code&gt; in &lt;code&gt;coop.rb&lt;/code&gt; to make it available.&lt;/p&gt;
&lt;h2 id=&quot;installing&quot;&gt;Installing&lt;a class=&quot;anchor&quot; href=&quot;#installing&quot; aria-label=&quot;Anchor link for: installing&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Great, now it can be easily installed:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt;brew&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; install&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-12&quot;&gt;-cask&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; rweir/tap/coop&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;testing&quot;&gt;Testing&lt;a class=&quot;anchor&quot; href=&quot;#testing&quot; aria-label=&quot;Anchor link for: testing&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Cool!  Now let&#39;s run it:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellsession&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;$&lt;/span&gt;&lt;span&gt; coop setup&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1&quot;&gt;zsh: killed     coop setup&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and the classic popup:&lt;/p&gt;
&lt;figure class=&quot;article-figure&quot;&gt;
  &lt;img src=&quot;https://ertius.org/til/2026-09-20/computer-says-no.png&quot; alt=&quot;macOS warning: Apple could not verify that coop is free of malware.&quot; width=&quot;526&quot; height=&quot;474&quot; style=&quot;width: 360px&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;figcaption&gt;Computer Says No&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;whelp&quot;&gt;Whelp&lt;a class=&quot;anchor&quot; href=&quot;#whelp&quot; aria-label=&quot;Anchor link for: whelp&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I could not find a single page describing all this (&lt;strong&gt;edit&lt;/strong&gt;: &lt;em&gt;I just found a pretty good doc on the Homebrew site, actually:&lt;/em&gt; &lt;a rel=&quot;external&quot; href=&quot;https://docs.brew.sh/Homebrew-Security-and-Supply-Chain#casks-have-a-different-trust-model&quot;&gt;Casks have a different trust model&lt;/a&gt;), but what&#39;s going on seems to be:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;macOS on AArch64 won&#39;t run ARM64 code that doesn&#39;t have a signature, but even an &quot;ad-hoc&quot; one is fine (&lt;a rel=&quot;external&quot; href=&quot;https://support.apple.com/en-au/guide/security/secebb113be1/1/web/1#sec75fb361d2&quot;&gt;source&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;The linker &lt;em&gt;does&lt;/em&gt; &lt;a rel=&quot;external&quot; href=&quot;https://users.rust-lang.org/t/how-to-create-macos-bundles-for-apple-silicon-they-always-seem-broken/132678/2&quot;&gt;sign the binaries&lt;/a&gt; from &lt;code&gt;cargo build&lt;/code&gt; with an ad-hoc signature, so that&#39;s fine&lt;/li&gt;
&lt;li&gt;Homebrew Cask &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Homebrew/brew/blob/edb70f031e4170c780799633a1226ff73e1077f4/Library/Homebrew/cask/quarantine.rb#L221&quot;&gt;marks downloaded binaries as downloaded&lt;/a&gt; by setting the &lt;code&gt;com.apple.quarantine&lt;/code&gt; xattr on them (and is quite reasonably &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Homebrew/brew/issues/20755#issuecomment-3330984446&quot;&gt;removing support for not doing that&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Trying to run a binary with the &lt;code&gt;quarantine&lt;/code&gt; xattr on it triggers Gatekeeper, which by default requires the binary to be both signed with an Apple Developer ID and then &lt;em&gt;also&lt;/em&gt; notarised by Apple.  Notarisation requires the binary be uploaded to Apple and pass some malware checks, and if it passes, Apple issues a notarisation ticket that Gatekeeper can verify.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can allow-list binaries, but it&#39;s being made increasingly difficult - Sequoia &lt;a rel=&quot;external&quot; href=&quot;https://developer.apple.com/news/?id=saqachfa&quot;&gt;removed the control-click&lt;/a&gt; workaround for this and the current workaround is a temporary button in Settings → Privacy &amp;amp; Security:&lt;/p&gt;
&lt;figure class=&quot;article-figure&quot;&gt;
  &lt;img src=&quot;https://ertius.org/til/2026-09-20/override.png&quot; alt=&quot;Settings dialog allowing binaries to be exempted from Gatekeeper so they can be run&quot; width=&quot;924&quot; height=&quot;183&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;figcaption&gt;Overriding it&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;So, that was something of a waste of time.  Options to make it work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get an Apple Developer account myself and have the binaries signed and notarised&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;xattr -d com.apple.quarantine&lt;/code&gt; to the cask and bypass all this&lt;/li&gt;
&lt;li&gt;Instead of a &lt;em&gt;cask&lt;/em&gt;, create a &lt;em&gt;formula&lt;/em&gt; that uses &lt;code&gt;bin.install&lt;/code&gt; to simply install the binaries rather than building them, avoiding Casks&#39;s provenance checks entirely and trusting upstream to not distribute malware, and ignoring the source entirely&lt;/li&gt;
&lt;li&gt;Document that one needs to go to Settings and click two buttons after install and every update&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;None of these are excellent, and the other-other option is: make a normal Homebrew formula instead, which downloads the source and builds it or uses &lt;a rel=&quot;external&quot; href=&quot;https://docs.brew.sh/Bottles&quot;&gt;prebuilt binary&lt;/a&gt; &lt;em&gt;bottles&lt;/em&gt;, which is what I&#39;ll do next.&lt;/p&gt;
&lt;p&gt;So, lesson learnt: &lt;em&gt;casks&lt;/em&gt; are only sensible for binaries where upstream has already interacted with Apple to have them signed and notarised.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Very Partial Git Commits</title>
        <published>2026-02-08T00:00:00+00:00</published>
        <updated>2026-02-08T00:00:00+00:00</updated>
        
        <author>
          <name>rweir@ertius.org (Rob Weir)</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://ertius.org/til/2026-02-08/"/><id>https://ertius.org/til/2026-02-08/</id>
        <content type="html" xml:base="https://ertius.org/til/2026-02-08/">&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://magit.vc&quot;&gt;&lt;code&gt;magit&lt;/code&gt;&lt;/a&gt; is of course the best &lt;code&gt;git&lt;/code&gt; client there
is, in particular because of how easy it makes curating the
index/staging area.  You can select individual hunks and go down to
marking individual lines for staging, and so I often end up spending a
lot of time crafting a commit.  A downside of this is that most of the
time my index is in some very specific state and so if I want to
commit something else, e.g. a typo fix or a dependency or something
that&#39;s not super related to the current change, I can&#39;t easily do so -
I would need to &lt;code&gt;stash&lt;/code&gt; and &lt;code&gt;add&lt;/code&gt; and &lt;code&gt;commit&lt;/code&gt; and &lt;code&gt;unstash&lt;/code&gt;, and so I
basically never do.&lt;/p&gt;
&lt;p&gt;Turns out someone thought of this and added a great new&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;https://ertius.org/til/2026-02-08/#fn-1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; feature to
&lt;code&gt;git&lt;/code&gt; - &lt;code&gt;-o&lt;/code&gt; / &lt;code&gt;--only&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ git add some_file.txt &amp;amp;&amp;amp; git commit -o -m&amp;quot;add some_file.txt&amp;quot; some_file.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A should-not-have-been-surprising-to-me quirk is that it&#39;s filtering
the &lt;em&gt;index&lt;/em&gt; not the tree, and so you need to stage it first.&lt;/p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://git.kernel.org/pub/scm/git/git.git/commit/?id=5a798fb57f&quot;&gt;added &lt;code&gt;2006-02-05 16:08:01 -0800&lt;/code&gt; to ... &lt;strong&gt;&lt;code&gt;git-commit.sh&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; &lt;a href=&quot;https://ertius.org/til/2026-02-08/#fr-1-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>I just want to mirror 10GB</title>
        <published>2026-02-05T00:00:00+00:00</published>
        <updated>2026-02-05T00:00:00+00:00</updated>
        
        <author>
          <name>rweir@ertius.org (Rob Weir)</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://ertius.org/til/2026-02-05/"/><id>https://ertius.org/til/2026-02-05/</id>
        <content type="html" xml:base="https://ertius.org/til/2026-02-05/">&lt;p&gt;I use a few third-party &lt;code&gt;apt&lt;/code&gt; repositories on my servers, which is
very convenient, but can also be slightly annoying:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;kanidm&lt;/code&gt; uses GitHub Pages, which still isn&#39;t available via IPv6 in
the year of our lord 2026&lt;/li&gt;
&lt;li&gt;&lt;code&gt;smallstep&lt;/code&gt; has some bizarre DNS load balancing config that is both
IPv4-only and has long &lt;code&gt;CNAME&lt;/code&gt; chains that make resolution
unreliable for me (which is possibly my fault!)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;incus&lt;/code&gt; releases very frequently and removes older packages, and I
prefer to pin exact package versions for big complicated (but good!
very good!) things like Incus which makes it regularly be
uninstallable on a new host because the last release I pinned is
gone from their repo&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, it seemed like time to set up a local mirror of this small amount of data
that I would like to have reliably available.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;debmirror&lt;/code&gt; was the obvious first choice for me, but no variation of
&lt;code&gt;--ignore=&quot;binary-all&quot;&lt;/code&gt; that I could contrive would make it stop
trying to fetch the non-existent &lt;code&gt;binary-all&lt;/code&gt; arch:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost systemd[1]: Starting debmirror@kanidm.service - Mirror third-party apt repository: kanidm...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462970]: === Syncing mirror: kanidm ===&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462970]: Host: kanidm.github.io&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462970]: Root: /kanidm_ppa&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462970]: Dists: bookworm,trixie&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462970]: Sections: stable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462970]: Archs: amd64,arm64&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462970]: Destination: /srv/apt-mirror/kanidm&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462970]: Running: debmirror --method=https --host=kanidm.github.io --root=/kanidm_ppa --dist=bookworm,trixie --section=stable --arch=amd64,arm64 --keyring=/etc/apt/keyrings/thirdparty-mirror/kanidm_ppa.gpg --nosource --ignore-missing-release --ignore-small-errors --timeout=300 --rsync-extra=none --diff=none --progress /srv/apt-mirror/kanidm&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462972]: Warning: --rsync-extra is not configured to mirror the trace files.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462972]:          This configuration is not recommended.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462972]: Mirroring to /srv/apt-mirror/kanidm from https://anonymous@kanidm.github.io/kanidm_ppa/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462972]: Arches: amd64,arm64&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462972]: Dists: bookworm,trixie&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462972]: Sections: stable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462972]: Pdiff mode: none&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462972]: Will clean up after mirroring.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462972]: Attempting to get lock ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462972]: Getting meta files ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462972]: [168B blob data]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462972]: ok&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462972]: [180B blob data]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:07 myhost debmirror-sync.sh[462972]: ok&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]: [149B blob data]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]: ok&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]: [196B blob data]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]: ok&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]: [208B blob data]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]: ok&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]: [140B blob data]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]: ok&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]: Ignoring missing Release file for dists/bookworm/stable/binary-all/Packages.gz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]: [235B blob data]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]: Download of dists/bookworm/stable/binary-all/Packages.gz failed: 404 Not Found&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]: Ignoring missing Release file for dists/trixie/stable/binary-all/Packages.gz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]: [231B blob data]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]: Download of dists/trixie/stable/binary-all/Packages.gz failed: 404 Not Found&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]: Failed to download some Package, Sources or Release files!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]: WARNING: releasing 1 pending lock...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]: Errors:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]:  Ignoring missing Release file for dists/bookworm/stable/binary-all/Packages.gz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]:  Download of dists/bookworm/stable/binary-all/Packages.gz failed: 404 Not Found&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]:  Ignoring missing Release file for dists/trixie/stable/binary-all/Packages.gz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462972]:  Download of dists/trixie/stable/binary-all/Packages.gz failed: 404 Not Found&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Feb 05 10:50:08 myhost debmirror-sync.sh[462970]: === Sync failed with exit code 2 ===&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(I think it is &lt;a rel=&quot;external&quot; href=&quot;https://bugs.debian.org/944139&quot;&gt;this bug&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;code&gt;aptly&lt;/code&gt; looked nice for try #2, and claims to support exactly this -
mirroring third party repositories - but as far as I could tell it had
no support for &lt;em&gt;mirroring&lt;/em&gt; repository &lt;em&gt;signatures&lt;/em&gt;, making clients in
2026 quite unhappy:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Error: The repository &amp;#39;https://somehost.example.org/thirdparty/kanidm trixie Release&amp;#39; is not signed.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Notice: Updating from such a repository can&amp;#39;t be done securely, and is therefore disabled by default.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I uh would really rather not have to set up my own secure remote
package signing system for my very basic mirror.&lt;/p&gt;
&lt;p&gt;Attempt #3 to just use &lt;code&gt;wget&lt;/code&gt; to spider files doesn&#39;t work since some
of the repositories are hosted on GitHub Pages, which doesn&#39;t do
normal directory indexes.&lt;/p&gt;
&lt;p&gt;Try #4 was &lt;code&gt;apt-mirror2&lt;/code&gt;, which is blessedly itself packaged in
Debian, and Just Works - it basically just takes some &lt;code&gt;sources.list&lt;/code&gt;
lines and some paths and does the thing:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# apt-mirror2 config for kanidm&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# Generated by Ansible&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set base_path         /srv/apt-mirror&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set mirror_path       /srv/apt-mirror/public&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set skel_path         /srv/apt-mirror/.skel&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set var_path          /srv/apt-mirror/.var&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set nthreads          4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set gpg_verify        on&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set etc_trusted_parts /srv/apt-mirror/.gnupg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;deb [arch=amd64,arm64 signed-by=/srv/apt-mirror/.gnupg/kanidm_ppa.gpg] https://kanidm.github.io/kanidm_ppa bookworm stable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;deb [arch=amd64,arm64 signed-by=/srv/apt-mirror/.gnupg/kanidm_ppa.gpg] https://kanidm.github.io/kanidm_ppa trixie stable&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is quite surprising that this is much much more fiddly than running
my own full-Debian mirror is - that was half an hour of fiddling with
&lt;a rel=&quot;external&quot; href=&quot;https://www.debian.org/mirror/ftpmirror&quot;&gt;&lt;code&gt;ftpsync&lt;/code&gt;&lt;/a&gt; and it was done.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Artisanal Filesystem Hacking With systemd</title>
        <published>2026-01-31T00:00:00+00:00</published>
        <updated>2026-01-31T00:00:00+00:00</updated>
        
        <author>
          <name>rweir@ertius.org (Rob Weir)</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://ertius.org/til/2026-01-31/"/><id>https://ertius.org/til/2026-01-31/</id>
        <content type="html" xml:base="https://ertius.org/til/2026-01-31/">&lt;p&gt;A service I started running some instances of a while ago is &lt;a rel=&quot;external&quot; href=&quot;https://atlas.ripe.net/&quot;&gt;RIPE
Atlas&lt;/a&gt;, a distributed dns/ping/traceroute
probing tool run by &lt;a rel=&quot;external&quot; href=&quot;https://www.ripe.net&quot;&gt;RIPE&lt;/a&gt;.  It is pretty easy
to deploy - they provide an &lt;code&gt;apt&lt;/code&gt; repository, that has a package in it
that installs an &lt;code&gt;apt&lt;/code&gt; config that gives you access to the packages.
Once it&#39;s installed, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/RIPE-NCC/ripe-atlas-probe-doc/blob/master/manuals/Debian13-binary.en.md&quot;&gt;it produces an SSH public
key&lt;/a&gt;
that you paste into a web page and away it goes.&lt;/p&gt;
&lt;p&gt;It is however not super flexible to operate.  One thing I wanted to do
was configure it to use an external resolver instead of the local
&lt;code&gt;unbound&lt;/code&gt; instance I have that is full of weird config hax for my
internal network.  As far as I could tell there&#39;s no config option
anywhere for this and I really wanted to avoid editing any of the
files in the package.  Once again, &lt;code&gt;systemd&lt;/code&gt; saves the day - just put
the resolver config in &lt;code&gt;/etc/ripe-atlas/resolv.conf&lt;/code&gt; and a drop-in
file in &lt;code&gt;/etc/systemd/system/ripe-atlas.service.d/dns.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-7&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-16&quot;&gt;Service&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-7&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-9 z-d-17&quot;&gt;BindReadOnlyPaths&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;=&lt;/span&gt;&lt;span&gt;/etc/ripe-atlas/resolv.conf:/etc/resolv.conf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;et voila.  Once again a thing I would probably not have bothered to do
in the pre-&lt;code&gt;systemd&lt;/code&gt; era - it is easy to add a &quot;mount --bind&quot; line to
a &lt;code&gt;sysvinit&lt;/code&gt; script but that would mean hacking a shell script from a
package (albeit a &lt;code&gt;conffile&lt;/code&gt;), which is annoying going forward
(telling &lt;code&gt;dpkg&lt;/code&gt; to leave it alone) and much more annoying to
automate - telling Ansible to insert a line into a text file in
roughly the right place is much more annoying than just dropping two
files on disk:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt; n&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;ame&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; D&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;eploy RIPE Atlas custom resolv.conf&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;  a&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;nsible.builtin.template&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;    s&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; r&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;ipe-atlas-resolv.conf.j2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;    d&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;est&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; /&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;etc/ripe-atlas/resolv.conf&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;    o&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;wner&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; r&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;oot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;    g&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;roup&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; r&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;oot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;    m&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;ode&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;0644&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;  n&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;otify&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;    -&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;RIPE Atlas : restart service&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt; n&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;ame&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; C&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;reate ripe-atlas service override directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;  a&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;nsible.builtin.file&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;    p&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;ath&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; /&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;etc/systemd/system/ripe-atlas.service.d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;    s&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;tate&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; d&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;irectory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;    o&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;wner&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; r&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;oot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;    g&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;roup&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; r&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;oot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;    m&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;ode&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;0755&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt; n&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;ame&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; D&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;eploy ripe-atlas DNS override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;  a&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;nsible.builtin.template&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;    s&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; r&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;ipe-atlas-dns.conf.j2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;    d&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;est&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; /&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;etc/systemd/system/ripe-atlas.service.d/dns.conf&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;    o&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;wner&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; r&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;oot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;    g&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;roup&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt; r&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;oot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;    m&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;ode&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;0644&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;  n&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4&quot;&gt;otify&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;    -&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;RIPE Atlas : daemon-reload&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-7&quot;&gt;    -&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;RIPE Atlas : restart service&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which is actually quite verbose, but is extremely straight-forward and
depends on the &lt;code&gt;systemd&lt;/code&gt; configuration merge semantics rather than
luck at automatically hacking shell scripts.  I actually started
writing out an equivalent attempt using &lt;code&gt;ansible.builtin.lineinfile&lt;/code&gt;
to edit an init script to add a &lt;code&gt;mount --bind&lt;/code&gt; line after the header
(not correctly in the &lt;code&gt;start&lt;/code&gt; and torn down in &lt;code&gt;stop&lt;/code&gt; since that seems
way too hard), then remembered that in that world I&#39;d first need to
write enough &lt;code&gt;sh&lt;/code&gt; to put this service in a &lt;code&gt;chroot&lt;/code&gt; to begin with, so
that I could customise the &lt;code&gt;/etc/resolv.conf&lt;/code&gt; it saw.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Zola Asset Integrity</title>
        <published>2026-01-12T00:00:00+00:00</published>
        <updated>2026-01-12T00:00:00+00:00</updated>
        
        <author>
          <name>rweir@ertius.org (Rob Weir)</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://ertius.org/til/2026-01-12/"/><id>https://ertius.org/til/2026-01-12/</id>
        <content type="html" xml:base="https://ertius.org/til/2026-01-12/">&lt;p&gt;As a diligent Over Engineer, a while ago I added two things to how
Zola generates links to assets:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;integrity&lt;/code&gt; attributes to CSS &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt;s, which means the browser
will reject CSS with the wrong hash&lt;/li&gt;
&lt;li&gt;&lt;code&gt;?h=0123456789abcdef&lt;/code&gt; faux-&lt;code&gt;GET&lt;/code&gt; params to the asset URLs
themselves, so that I can set long HTTP cache times on them&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That looks like this in a Zola template:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-3&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4 z-d-b&quot;&gt;link&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-16&quot;&gt;    integrity&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;sha384-{{ get_hash(path=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-16&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;z-l-7 z-l-i z-d-11&quot;&gt;/some.css&amp;quot;,&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-16&quot;&gt; sha_type&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;384,&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-16&quot;&gt; base64&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;true)&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-16&quot;&gt; |&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-16&quot;&gt; safe&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-16&quot;&gt; }}&lt;/span&gt;&lt;span class=&quot;z-l-7 z-l-i z-d-11&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-16&quot;&gt;    rel&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;stylesheet&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-16&quot;&gt; href&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;{{ get_url(cachebust=true, path=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-16&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;z-l-7 z-l-i z-d-11&quot;&gt;/some.css&amp;quot;)&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-16&quot;&gt; }}&lt;/span&gt;&lt;span class=&quot;z-l-7 z-l-i z-d-11&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which produces output like this in the generated HTML:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-d-3&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-4 z-d-b&quot;&gt;link&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-16&quot;&gt;    integrity&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;sha384-6d001da919b965dc3a4672b9d7ddce374d165452a2285f2753988842092ea6b9946645375cff3ede89a991c9698bfcea&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-16&quot;&gt;    rel&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;stylesheet&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-16&quot;&gt; href&lt;/span&gt;&lt;span class=&quot;z-d-7&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-9&quot;&gt;/css/some.css?h=0123456789abcdef&lt;/span&gt;&lt;span class=&quot;z-l-3 z-d-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-d-3&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Thus letting the HTML assert what the assets loaded for it should look
like.  So, now, if a malicious TLA MITMs you or compromises the server
serving static assets, the browser will reject them (from the console
log):&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[Error] Cannot load stylesheet http://127.0.0.1:1111/css/main.css?h=0123456789abcdef. Failed integrity metadata check. Content length: 7715, Expected content length:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7715, Expected metadata: sha384-6d001da919b965dc3a4672b9d7ddce374d165452a2285f2753988842092ea6b9946645375cff3ede89a991c9698bfcea&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In other news, Zola has a &lt;code&gt;serve&lt;/code&gt;
&lt;a rel=&quot;external&quot; href=&quot;https://www.getzola.org/documentation/getting-started/cli-usage/#serve&quot;&gt;command&lt;/a&gt;
that runs a little dev server and reloads if any of the files change:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;❯ mise run serve&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[serve] $ zola serve --interface 0.0.0.0 --base-url / --port=${PORT:-1111} --drafts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Building site...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Checking all internal links with anchors.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; Successfully checked 0 internal link(s) with anchors.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&amp;gt; Creating 1 pages (0 orphan) and 0 sections&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Done in 7ms.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Web server is available at / (bound to 0.0.0.0:1111)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Listening for changes in /home/user/project/{config.toml,content,static,templates}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Press Ctrl+C to stop&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Change detected @ 2026-01-12 15:03:46&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&amp;gt; Static file changed /home/user/project/static/css/some.css&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Done in 2ms.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can see at the bottom that it reloaded the CSS file that had changed.&lt;/p&gt;
&lt;p&gt;Unfortunately, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/getzola/zola/issues/1817&quot;&gt;Zola doesn&#39;t tie these two features
together&lt;/a&gt; and if you use
integrity and edit the assets while &lt;code&gt;zola&lt;/code&gt; is running, then it will
start serving the new asset with the old HTML, and then the browser
will quite reasonably tell you to fuck off and stop loading the CSS.
Excitingly, browsers don&#39;t really show that this is happening anywhere
&lt;em&gt;except&lt;/em&gt; in the console log, and if you have multiple style sheets and
edited only one, the behaviour you will see is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;everything is fine&lt;/li&gt;
&lt;li&gt;edit a CSS file&lt;/li&gt;
&lt;li&gt;reload page&lt;/li&gt;
&lt;li&gt;styles are all fucked up, and if you&#39;re like me, assume it&#39;s
because your edit was terrible&lt;/li&gt;
&lt;li&gt;think that&#39;s weird, let&#39;s blame caching or something&lt;/li&gt;
&lt;li&gt;restart zola&lt;/li&gt;
&lt;li&gt;everything is fine&lt;/li&gt;
&lt;li&gt;undo change to CSS file&lt;/li&gt;
&lt;li&gt;styles are all fucked up, and if you&#39;re like me, assume it&#39;s
because your edit was terrible&lt;/li&gt;
&lt;li&gt;etc&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;On the bug, user &lt;a rel=&quot;external&quot; href=&quot;https://github.com/legoktm&quot;&gt;legoktm&lt;/a&gt; provides a
&lt;a rel=&quot;external&quot; href=&quot;https://github.com/getzola/zola/issues/1817#issuecomment-2692552878&quot;&gt;pretty good
workaround&lt;/a&gt;,
that just removes the integrity attribute entirely when in local dev
serving mode:&lt;/p&gt;
&lt;p&gt;Firstly, add a new macro in &lt;code&gt;templates/macros.html&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% macro sri(path) -%}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% if config.mode != &amp;quot;serve&amp;quot; -%}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;integrity=&amp;quot;sha384-{{ get_hash(path=path, sha_type=384, base64=true) | safe }}&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{%- endif %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{%- endmacro %}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then at the top of &lt;code&gt;templates/base.html&lt;/code&gt; (or wherever your &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; tags are done):&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% import &amp;quot;macros.html&amp;quot; as macros %}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and wherever you actually write out the &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; in the templates, do this instead:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;{{ get_url(path=&amp;quot;static/some.css&amp;quot;, cachebust=true) }}&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {{macros::sri(path=&amp;quot;static/some.css&amp;quot;)}} /&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Git Spelunking</title>
        <published>2026-01-02T00:00:00+00:00</published>
        <updated>2026-01-02T00:00:00+00:00</updated>
        
        <author>
          <name>rweir@ertius.org (Rob Weir)</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://ertius.org/til/2026-01-02/"/><id>https://ertius.org/til/2026-01-02/</id>
        <content type="html" xml:base="https://ertius.org/til/2026-01-02/">&lt;p&gt;I wanted to find something in some commit, and while trying to
remember the right way to wrap around &lt;code&gt;git rev-list --all&lt;/code&gt;, I found
that &lt;code&gt;git&lt;/code&gt; grew an option to just do that: &lt;code&gt;git log -G&amp;lt;regexp&amp;gt; --branches --all&lt;/code&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;https://ertius.org/til/2026-01-02/#fn-1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;And when was it added?  Let&#39;s find out:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;❯ git log -G&amp;quot;-G&amp;quot; --pretty=format:&amp;quot;%h%x09%x09%ad%x09%s&amp;quot; --reverse -- Documentation/diff-options.txt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;f506b8e8b5      2010-08-23 10:17:03 -0700   git log/diff: add -G&amp;lt;regexp&amp;gt; that greps in the patch text&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5bc3f0b567      2013-05-31 17:42:15 +0530   diffcore-pickaxe doc: document -S and -G properly&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9299f84921      2020-02-06 21:53:01 +0100   diff-options.txt: avoid &amp;quot;regex&amp;quot; overload in example&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;6b552e39c0      2024-11-18 22:05:50 +0000   doc: git-diff: apply format changes to diff-options&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1f010d6bdf      2025-01-20 01:56:02 +0000   doc: use .adoc extension for AsciiDoc files&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://stackoverflow.com/a/2928721&quot;&gt;https://stackoverflow.com/a/2928721&lt;/a&gt; &lt;a href=&quot;https://ertius.org/til/2026-01-02/#fr-1-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
        
    </entry>
</feed>
