<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>markpenner.space - Blog</title>
    <link>https://markpenner.space/blog/</link>
    <description>markpenner.space</description>
    <generator>Zola</generator>
    <language>en</language>
    <atom:link href="https://markpenner.space/blog/index.xml" rel="self" type="application/rss+xml"/>
    <lastBuildDate>Mon, 25 May 2026 00:00:00 +0000</lastBuildDate>
    <item>
      <title>Controlling a Quest M6 Roaster with Phidgets and C++</title>
      <link>https://markpenner.space/blog/2026-05-25-controlling-roaster/</link>
      <pubDate>Mon, 25 May 2026 00:00:00 +0000</pubDate>
      <author>Mark Penner</author>
      <guid>https://markpenner.space/blog/2026-05-25-controlling-roaster/</guid>
      <description>&lt;p&gt;I have a &lt;a href=&quot;https://www.coffeeshrub.com/quest-m6-coffee-roaster.html&quot;&gt;Quest M6&lt;/a&gt; coffee roaster.
It is a small electric drum roaster that comes with manual &lt;a href=&quot;https://en.wikipedia.org/wiki/Phase-fired_controller&quot;&gt;phase-control dimmers&lt;/a&gt; for the fan and heater.
I set up some &lt;a href=&quot;https://www.phidgets.com/&quot;&gt;Phidgets&lt;/a&gt; with thermocouples to report the bean temperature and roasting environment temperature to &lt;a href=&quot;https://artisan-scope.org/&quot;&gt;Artisan&lt;/a&gt;.
When I adjusted the heater setting I would also manually enter the setting change in Artisan.
I got to thinking it would be nice if I could just enter the desired change in Artisan and that would also set the heater.
So the journey begins.&lt;/p&gt;
&lt;p&gt;Since I was already using Phidgets for temperature readings, I got a &lt;a href=&quot;https://www.phidgets.com/?tier=3&amp;amp;catid=2&amp;amp;pcid=1&amp;amp;prodid=714&quot;&gt;Digital Output Phidget&lt;/a&gt; that can output a &lt;a href=&quot;https://en.wikipedia.org/wiki/Pulse-width_modulation&quot;&gt;PWM&lt;/a&gt; (pulse-width modulated) signal.
The Digital Output Phidget doesn&#39;t have a zero crossing detector to synchronize with the AC grid power, so I planned to use a zero-crossing &lt;a href=&quot;https://en.wikipedia.org/wiki/Solid-state_relay&quot;&gt;SSR&lt;/a&gt; to switch at a frequency much lower than the 60 Hz grid.
Unfortunately I hadn&#39;t read the specifications carefully enough, and realized after I got it and started testing it out that the minimum PWM frequency from the Digital Output Phidget is 100 Hz.
It doesn&#39;t really work to use a 100 Hz signal to switch 60 Hz power at the zero crossings.
What to do now?&lt;/p&gt;
&lt;p&gt;I could have gotten a different device at this point, like a &lt;a href=&quot;https://www.tindie.com/products/greencardigan/tc4-arduino-shield-v7-00/&quot;&gt;TC4&lt;/a&gt; or a &lt;a href=&quot;https://www.yoctopuce.com/EN/products/usb-electrical-interfaces/yocto-pwm-tx&quot;&gt;Yocto-PWM-Tx&lt;/a&gt;.
However, I didn&#39;t really feel like spending more money, and I had gotten an idea to make what I already had work.
I could &lt;a href=&quot;https://en.wikipedia.org/wiki/Bit_banging&quot;&gt;bit bang&lt;/a&gt; the PWM instead of using the Digital Output Phidget&#39;s PWM functionality.
All it would take is a little programming to communicate with Artisan and to turn the output on and off with the right timing.&lt;/p&gt;
&lt;p&gt;Artisan can talk directly to Phidgets, but it can also talk to other &lt;a href=&quot;https://artisan-scope.org/devices/&quot;&gt;devices&lt;/a&gt;.
One of the protocols it can talk is &lt;a href=&quot;https://artisan-scope.org/devices/websockets/&quot;&gt;JSON over WebSockets&lt;/a&gt;.
I could build a WebSocket server that would talk to the Phidgets, and Artisan could talk to my server.&lt;/p&gt;
&lt;p&gt;I thought briefly about using this as an opportunity to learn Go or Rust or Zig or some other language, but I wanted something quickly and I knew performance (low latency specifically) would matter, so I went with C++.
I&#39;m not an expert C++ programmer, but I have enough experience that I was confident I could do what I needed to do.
My experience with C++ has largely been with KDE applications and libraries, so it was an interesting change to build a server program instead.&lt;/p&gt;
&lt;p&gt;There is a C library for communicating with Phidgets, so that was easy enough to interface with from C++.
I made a wrapper class to handle the details of working with the Phidgets C API.
For WebSocket and JSON support, I chose &lt;a href=&quot;https://www.boost.org/library/latest/beast/&quot;&gt;Boost.Beast&lt;/a&gt; and &lt;a href=&quot;https://www.boost.org/library/latest/json/&quot;&gt;Boost.JSON&lt;/a&gt;.
I hadn&#39;t worked with Boost libraries directly before, since I had worked mainly with Qt-based software, but I have been happy so far.
Beast can do much more than I am using it for.
There are several different APIs you can use and it was a bit hard to wrap my head around them all at once.
I&#39;m using the synchronous API for now since it seemed the easiest to understand.&lt;/p&gt;
&lt;p&gt;I implemented pulse-width modulation by starting a thread and passing the duty cycle in as a reference to a number between 0 and 1, stored in a &lt;a href=&quot;https://en.cppreference.com/cpp/atomic/atomic&quot;&gt;&lt;code&gt;std::atomic&lt;/code&gt;&lt;/a&gt; so I could change it atomically from a different thread.
The PWM thread runs a loop turning the output on, sleeping for the period duration multiplied by the duty cycle (between 0 and 1), then turns the output off and sleeps for the period multiplied by 1 minus the duty cycle.
I&#39;m not sure if there&#39;s a better way to implement this than sleeping the thread, but it&#39;s working for me.&lt;/p&gt;
&lt;p&gt;Then I got to thinking again.
I was using a fixed length period of 0.83 seconds to cover 50 full cycles of 60 Hz, so when the duty cycle was at 0.5, the heater would be on for 25 cycles and off for 25 cycles.
The period could be made shorter on average be implementing a duty cycle of 0.5 as 1 cycle on, 1 cycle off, and 0.75 would be 3 cycles on, 1 cycle off, etc.
This is &lt;a href=&quot;https://en.wikipedia.org/wiki/Pulse-density_modulation#Relationship_to_PWM&quot;&gt;pulse-density modulation&lt;/a&gt; instead of pulse-width modulation.&lt;/p&gt;
&lt;p&gt;The duty cycle setting comes from Artisan as a number between 0 and 100, so rather than converting that to a floating point number between 0 and 1, I simplified the fraction of the duty cycle over 100, e.g. 75 over 100 becomes 3 over 4, which means 3 cycles on and 4 - 3 = 1 cycle off.
The heater control thread received a pair of integers instead of a single floating point number, and multiplied them by 1/60th of a second (full wave of 60 Hz power) to get the on and off durations.&lt;/p&gt;
&lt;p&gt;An electric heater responds so slowly that shortening the period like this doesn&#39;t make much difference in controlling it.
The main advantage was that it was usually switching fast enough that the watt meter I plugged my roaster into read the average wattage being used.
However, the ceiling lights dim when the heater is on full power, and switching like that makes them flicker annoyingly.
For now I decided to go back to PWM at a fixed period of 1.67 seconds (100 cycles of 60 Hz), which is slow enough that the lights dimming and brightening doesn&#39;t bother me.
The watt meter reading now jumps up and down instead of reading an average, but I don&#39;t rely on it anymore anyway, so that&#39;s alright.&lt;/p&gt;
&lt;p&gt;You can see the code at &lt;a href=&quot;https://codeberg.org/mrp/ossicle&quot;&gt;https://codeberg.org/mrp/ossicle&lt;/a&gt;.
There is currently some stuff hard coded for my own use: my Phidget setup and the port the WebSocket server runs on.
If others want to use it and would rather have that configurable some other way than recompiling, open an &lt;a href=&quot;https://codeberg.org/mrp/ossicle/issues&quot;&gt;issue&lt;/a&gt; or &lt;a href=&quot;https://codeberg.org/mrp/ossicle/pulls&quot;&gt;PR&lt;/a&gt;.
I may try reimplementing it in a different language for a learning experience sometime, but I&#39;m happy with the project for now.&lt;/p&gt;
&lt;p&gt;I&#39;m very happy with how easy the Quest M6 is to modify for projects like this.
It is very well built, easy to understand, and easy to work on.
It works great in stock condition as a manual roaster and also makes a good base for modifications.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Kwave Nightly Flatpak</title>
      <link>https://markpenner.space/blog/2025-01-06-kwave-flatpak/</link>
      <pubDate>Mon, 06 Jan 2025 22:25:00 -0600</pubDate>
      <author>Mark Penner</author>
      <guid>https://markpenner.space/blog/2025-01-06-kwave-flatpak/</guid>
      <description>&lt;p&gt;If you want to keep up with the latest Kwave updates, you can now try out the nightly flatpak. It
gets published each time code is pushed to the master branch, so it may sometimes have bugs, but
also new features. To try it out, add the repository by running &lt;code&gt;flatpak remote-add kwave-nightly https://cdn.kde.org/flatpak/kwave-nightly/kwave-nightly.flatpakrepo&lt;/code&gt; and install Kwave with &lt;code&gt;flatpak install kwave-nightly org.kde.kwave&lt;/code&gt;. If you use &lt;a href=&quot;https://apps.kde.org/discover/&quot;&gt;Discover&lt;/a&gt;, go to
Settings, click Add Source and paste
&lt;code&gt;https://cdn.kde.org/flatpak/kwave-nightly/kwave-nightly.flatpakrepo&lt;/code&gt; in to add the repo, and then
search for Kwave.&lt;/p&gt;
&lt;p&gt;The process for publishing stable versions to Flathub has also
&lt;a href=&quot;https://github.com/flathub/flathub/pull/5993&quot;&gt;started&lt;/a&gt;. The current plan is to wait for the next
stable version (25.04) to publish Kwave on Flathub.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Kwave Update - October 2024</title>
      <link>https://markpenner.space/blog/2024-10-28-kwave-update/</link>
      <pubDate>Mon, 28 Oct 2024 00:00:00 +0000</pubDate>
      <author>Mark Penner</author>
      <guid>https://markpenner.space/blog/2024-10-28-kwave-update/</guid>
      <description>&lt;p&gt;&lt;a href=&quot;https://apps.kde.org/kwave&quot;&gt;Kwave&lt;/a&gt; is an audio editor based on the KDE Frameworks. It was started
in 1998 by Martin Wilz, and Thomas Eschenbacher has been the main developer since 1999. In recent
years development has slowed. I wanted to do some software development and contribute to KDE, and
I&#39;m interested in audio, so towards the end of 2023 I started working on Kwave.&lt;/p&gt;
&lt;p&gt;Kwave had not been ported to Qt 6 and KDE Frameworks 6 yet, so that&#39;s what I started working towards.
My first merge requests were to update deprecated code. (MR &lt;a href=&quot;https://invent.kde.org/multimedia/kwave/-/merge_requests/15&quot;&gt;Convert plugin desktop files to
json&lt;/a&gt;, MR &lt;a href=&quot;https://invent.kde.org/multimedia/kwave/-/merge_requests/16&quot;&gt;Port away from deprecated Qt
API&lt;/a&gt;, MR &lt;a href=&quot;https://invent.kde.org/multimedia/kwave/-/merge_requests/17&quot;&gt;port away from deprecated
I18N_NOOP macros&lt;/a&gt;, MR &lt;a href=&quot;https://invent.kde.org/multimedia/kwave/-/merge_requests/18&quot;&gt;bump
KF5_MIN_VERSION and update where KMessageBox API has been
deprecated&lt;/a&gt;, MR &lt;a href=&quot;https://invent.kde.org/multimedia/kwave/-/merge_requests/21&quot;&gt;port QRegExp to
QRegularExpression&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;With that preparatory work done, I worked at porting Kwave to Qt 6 and KDE Frameworks 6. Most of
that work was straight-forward. The biggest changes were in Qt Multimedia, which Kwave can use for
playback and recording. I finally got that done and merged in August 2024, just after version 24.08
was branched, so that change will get released in version 24.12 in December 2024. (MR &lt;a href=&quot;https://invent.kde.org/multimedia/kwave/-/merge_requests/22&quot;&gt;port to Qt6
and KF6&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Next I did some code cleanup. (MR &lt;a href=&quot;https://invent.kde.org/multimedia/kwave/-/merge_requests/23&quot;&gt;use
ECMGenerateExportHeader&lt;/a&gt;, MR &lt;a href=&quot;https://invent.kde.org/multimedia/kwave/-/merge_requests/25&quot;&gt;add
braces to avoid ambiguous else&lt;/a&gt;, MR
&lt;a href=&quot;https://invent.kde.org/multimedia/kwave/-/merge_requests/26&quot;&gt;call KCrash::initialize() after
KAboutData::setApplicationData()&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Laurent Montel added the FreeBSD job to the Continuous Integration configuration, but the build
failed initially. I&#39;ve never ran FreeBSD, but with a few tries and pushing changes to trigger CI, I
managed to get the CI to pass. I&#39;m glad Laurent took the initiative here, because the FreeBSD job
uses clang, so with the existing Linux job using gcc, CI makes sure Kwave builds with both compilers
now. (MR &lt;a href=&quot;https://invent.kde.org/multimedia/kwave/-/merge_requests/24&quot;&gt;Add freebsd&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;I applied for a &lt;a href=&quot;https://community.kde.org/Infrastructure/Get_a_Developer_Account&quot;&gt;KDE Developer
account&lt;/a&gt; and got approved on
August 24, 2024. Now I could commit changes myself instead of having to remind others to do it.&lt;/p&gt;
&lt;p&gt;Carl Schwan cleaned up some code and updated the zoom toolbar to use standard icons, which enabled
removing the built-in zoom icons. (MR &lt;a href=&quot;https://invent.kde.org/multimedia/kwave/-/merge_requests/27&quot;&gt;Modernize
ZoomToolbar&lt;/a&gt;) That was the incentive I
needed to remove the rest of the built-in icons and use standard icons instead, which helps Kwave
fit the users theme better. (MR &lt;a href=&quot;https://invent.kde.org/multimedia/kwave/-/merge_requests/29&quot;&gt;use icons from current
theme&lt;/a&gt;) I also reordered the playback
toolbar in a way that seemed more logical to me. (MR &lt;a href=&quot;https://invent.kde.org/multimedia/kwave/-/merge_requests/30&quot;&gt;update player
toolbar&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;I investigated a bug: &lt;a href=&quot;https://bugs.kde.org/show_bug.cgi?id=439543&quot;&gt;Kwave Playback settings dialog loads incorrectly until you switch playback
methods&lt;/a&gt; and fixed it in MR: &lt;a href=&quot;https://invent.kde.org/multimedia/kwave/-/merge_requests/33&quot;&gt;make sure a valid method
gets selected when PlayBackDialog
opens&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I have some more work in progress, and I plan to continue working on Kwave. I will try to blog about
what I&#39;m doing, but I&#39;m not going to commit to any regular schedule.&lt;/p&gt;
&lt;h3 id=&quot;get-involved&quot;&gt;Get Involved&lt;/h3&gt;
&lt;p&gt;Kwave depends on the rest of KDE. It is built on the
&lt;a href=&quot;https://develop.kde.org/products/frameworks/&quot;&gt;Frameworks&lt;/a&gt;, and the KDE sysadmin team keeps the
infrastructure running. You can help KDE by &lt;a href=&quot;https://community.kde.org/Get_Involved&quot;&gt;getting
involved&lt;/a&gt;, or at least &lt;a href=&quot;https://kde.org/donate/&quot;&gt;donate&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you would like to help improve Kwave, use it and try out its features! If you have questions or
ideas, &lt;a href=&quot;https://discuss.kde.org/tag/kwave&quot;&gt;discuss&lt;/a&gt; them. If you find bugs, &lt;a href=&quot;https://bugs.kde.org/enter_bug.cgi?product=kwave&amp;amp;component=general&quot;&gt;report
them&lt;/a&gt;. If you want to get
involved with development, download the &lt;a href=&quot;https://invent.kde.org/multimedia/kwave&quot;&gt;source code&lt;/a&gt; and
start hacking!&lt;/p&gt;
&lt;p&gt;If you think my own work on Kwave is worth something and you can afford it, you can donate to me
through &lt;a href=&quot;https://liberapay.com/mrp/donate&quot;&gt;Liberapay&lt;/a&gt;,
&lt;a href=&quot;https://donate.stripe.com/eVa29p7JZ9xydRCbII&quot;&gt;Stripe&lt;/a&gt;, or &lt;a href=&quot;https://paypal.me/mrpenner&quot;&gt;PayPal&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>How to build a Debian metapackage for personal use</title>
      <link>https://markpenner.space/blog/2023-09-23-howto-build-debian-metapackage/</link>
      <pubDate>Sat, 23 Sep 2023 00:00:00 +0000</pubDate>
      <author>Mark Penner</author>
      <guid>https://markpenner.space/blog/2023-09-23-howto-build-debian-metapackage/</guid>
      <description>&lt;h3 id=&quot;why-build-your-own-metapackage&quot;&gt;Why build your own metapackage?&lt;/h3&gt;
&lt;p&gt;I don&#39;t like having lots of manually installed packages that I&#39;m not sure I need on my Debian system. One way I get such packages is when I&#39;m compiling software such as FreeCad, and I install the build dependencies with a command like the one that is listed &lt;a href=&quot;https://wiki.freecad.org/Compile_on_Linux#Single_command_for_Python_3_and_Qt5&quot;&gt;here&lt;/a&gt;. (That command doesn&#39;t actually work on Debian unstable, I got my list of packages to install from &lt;a href=&quot;https://salsa.debian.org/science-team/freecad/-/blob/master/debian/control?ref_type=heads&quot;&gt;here&lt;/a&gt;.) When you run a command like that, all those packages are marked as manually installed. I had the idea to build a metapackage that depends on those packages, so if I decide I won&#39;t be building FreeCad again I can uninstall the metapackage and if nothing else depends on those packages they can be removed with &lt;code&gt;sudo apt autoremove&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Most of this is based on the &lt;a href=&quot;https://wiki.debian.org/Packaging/Intro&quot;&gt;packaging intro tutorial&lt;/a&gt; on the Debian wiki. Check that out if you want more details. This howto will give just enough information to get this metapackage built, because that is the extent of my experience so far. ;-)&lt;/p&gt;
&lt;h3 id=&quot;install-the-packages-you-will-need&quot;&gt;Install the packages you will need&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;sudo apt install build-essential devscripts debhelper&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;(Here you might think about building a metapackage for building metapackages. Very meta.)&lt;/p&gt;
&lt;h3 id=&quot;make-the-directory-structure-and-switch-into-it&quot;&gt;Make the directory structure and switch into it&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;mkdir -p ~/deb/build-dependencies/debian/; cd ~/deb/build-dependencies/&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In this structure, &lt;code&gt;deb/&lt;/code&gt; will be where the final .deb file will end up. Under that, &lt;code&gt;build-dependencies/&lt;/code&gt; is the package directory, which since this is a metapackage, will be empty except for the &lt;code&gt;debian/&lt;/code&gt; directory, where the package metadata files will go.&lt;/p&gt;
&lt;h3 id=&quot;generate-a-changelog-in-the-right-format&quot;&gt;Generate a changelog in the right format&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;dch --create -v 1 --package build-dependencies&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;-v 1&lt;/code&gt; switch sets the package version to 1. This will make a &lt;code&gt;debian/changelog&lt;/code&gt; file. I got a warning &lt;code&gt;neither DEBEMAIL nor EMAIL environment variable is set&lt;/code&gt;. Press Enter to accept the warning and your editor will pop up to edit the created file. You can delete the &lt;code&gt;(Closes: #XXXXXX)&lt;/code&gt; bit and edit the last line that has your name and email address if you want. The email address does not need to be valid (since I won&#39;t be uploading this to Debian), but there does need to be something there else the package won&#39;t build.&lt;/p&gt;
&lt;h3 id=&quot;the-copyright-file-needs-to-exist-but-it-can-be-empty&quot;&gt;The copyright file needs to exist, but it can be empty&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;touch debian/copyright&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;now-the-interesting-file-debian-control&quot;&gt;Now the interesting file: &lt;code&gt;debian/control&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The first part, &lt;code&gt;Source: build-dependencies&lt;/code&gt;, is the source package metadata. The second part, &lt;code&gt;Package: freecad-dependencies&lt;/code&gt;, is the binary package metadata. The binary package is what you actually install, and you can make more than one binary package from one source package by providing several &lt;code&gt;Package: binary-package-name&lt;/code&gt; sections.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #4C4F69; background-color: #EFF1F5;&quot; &gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;Source&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; build-dependencies&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;Maintainer&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; Mark Penner&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;Section&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; misc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;Priority&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; optional&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;Build-Depends&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; debhelper-compat (= 13)&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 style=&quot;color: #1E66F5;&quot;&gt;Package&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; freecad-dependencies&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;Architecture&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; any&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;Depends&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; cmake,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libboost-date-time-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libboost-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libboost-filesystem-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libboost-graph-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libboost-iostreams-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libboost-program-options-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libboost-python-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libboost-regex-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libboost-serialization-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libboost-thread-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libcoin-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libdouble-conversion-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libglew-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         liblz4-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libopencv-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libeigen3-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libgts-bin,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libgts-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libkdtree++-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libmedc-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libmetis-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libocct-data-exchange-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libocct-ocaf-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libocct-visualization-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libpyside2-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libqt5opengl5-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libqt5svg5-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libqt5xmlpatterns5-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libqt5x11extras5-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libshiboken2-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libspnav-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libvtk9-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libx11-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libxerces-c-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         libzipios++-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         lsb-release,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         occt-draw,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         pybind11-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         pyqt5-dev-tools,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         pyside2-tools,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         python3-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         python3-matplotlib,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         python3-ply,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         python3-pyside2.qtcore,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         python3-pyside2.qtgui,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         python3-pyside2.qtsvg,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         python3-pyside2.qtuitools,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         python3-pyside2.qtwidgets,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         python3-pyside2.qtxml,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         python3-requests,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         qtbase5-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         qttools5-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         qtwebengine5-dev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;         swig&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;Description&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; FreeCad build dependencies&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; Metapackage to install dependencies for building FreeCad.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;debian-rules-is-a-makefile-with-instructions-to-build-the-package&quot;&gt;&lt;code&gt;debian/rules&lt;/code&gt; is a Makefile with instructions to build the package&lt;/h3&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #4C4F69; background-color: #EFF1F5;&quot; &gt;&lt;code data-lang=&quot;make&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7C7F93;font-style: italic;&quot;&gt;#!/usr/bin/make -f&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	dh $@&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Remember Makefiles use tabs not spaces!&lt;/p&gt;
&lt;h3 id=&quot;build-the-package&quot;&gt;Build the package&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;debuild&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The package will be built and placed in the directory above the one you&#39;re in. (&lt;code&gt;deb/freecad-dependencies_1_amd64.deb&lt;/code&gt; is the built binary package on my machine.)&lt;/p&gt;
&lt;h3 id=&quot;install&quot;&gt;Install&lt;/h3&gt;
&lt;p&gt;Now if all the dependencies are already installed, you can run &lt;code&gt;sudo debi&lt;/code&gt; to install the package. It will find the package in the directory above and install it with dpkg. However, dpkg will not install dependencies for you. Since I made this package specifically to install dependencies, I ran &lt;code&gt;sudo apt install ../freecad-dependencies_1_amd64.deb&lt;/code&gt;. That installed all the dependencies, and also the dependencies of dependencies.&lt;/p&gt;
&lt;h3 id=&quot;celebrate-a-cleaner-manually-installed-packages-list&quot;&gt;Celebrate a cleaner manually installed packages list!&lt;/h3&gt;
&lt;p&gt;If any of those packages were already installed, you can mark them as automatically installed with:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sudo apt-mark auto cmake libboost-date-time-dev libboost-dev libboost-filesystem-dev libboost-graph-dev libboost-iostreams-dev libboost-program-options-dev libboost-python-dev libboost-regex-dev libboost-serialization-dev libboost-thread-dev libcoin-dev libdouble-conversion-dev libglew-dev liblz4-dev libopencv-dev libeigen3-dev libgts-bin libgts-dev libkdtree++-dev libmedc-dev libmetis-dev libocct-data-exchange-dev libocct-ocaf-dev libocct-visualization-dev libpyside2-dev libqt5opengl5-dev libqt5svg5-dev libqt5xmlpatterns5-dev libqt5x11extras5-dev libshiboken2-dev libspnav-dev libvtk9-dev libx11-dev libxerces-c-dev libzipios++-dev lsb-release occt-draw pybind11-dev pyqt5-dev-tools pyside2-tools python3-dev python3-matplotlib python3-ply python3-pyside2.qtcore python3-pyside2.qtgui python3-pyside2.qtsvg python3-pyside2.qtuitools python3-pyside2.qtwidgets python3-pyside2.qtxml python3-requests qtbase5-dev qttools5-dev qtwebengine5-dev swig&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;next&quot;&gt;Next&lt;/h3&gt;
&lt;p&gt;Now if when I try to compile FreeCad I need other packages installed, I can just add them to &lt;code&gt;debian/control&lt;/code&gt;, build the package again, and reinstall.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Blogging With Hugo and Org-mode</title>
      <link>https://markpenner.space/blog/2023-08-02-blogging-hugo-org-mode/</link>
      <pubDate>Wed, 02 Aug 2023 00:00:00 +0000</pubDate>
      <author>Mark Penner</author>
      <guid>https://markpenner.space/blog/2023-08-02-blogging-hugo-org-mode/</guid>
      <description>&lt;p&gt;This blog was originally generated with &lt;a href=&quot;https://gohugo.io&quot;&gt;Hugo&lt;/a&gt;.
I&#39;m leaving this post up for the record, but it is no longer how I build this site.&lt;/p&gt;
&lt;p&gt;I set it up a bit differently than many tutorials, so I thought I would describe what I did and why. I did not use a &lt;a href=&quot;https://themes.gohugo.io&quot;&gt;theme&lt;/a&gt;; I just wrote a few layouts and a short CSS file for a &lt;a href=&quot;https://brutalist-web.design&quot;&gt;brutalist design&lt;/a&gt;. I wanted to be able to understand and control my design rather than try to figure out how to get what I wanted out of an existing theme.&lt;/p&gt;
&lt;p&gt;I like the &lt;a href=&quot;https://karl-voit.at/2017/09/23/orgmode-as-markup-only/&quot;&gt;expressivity and clarity&lt;/a&gt; of &lt;a href=&quot;https://orgmode.org/&quot;&gt;Org mode&lt;/a&gt; syntax rather than Markdown. Thankfully, Hugo &lt;a href=&quot;https://gohugo.io/content-management/formats/#list-of-content-formats&quot;&gt;can read Org files&lt;/a&gt; good enough for me. &lt;a href=&quot;https://github.com/niklasfasching/go-org&quot;&gt;go-org&lt;/a&gt;, the library Hugo uses to parse Org files, is intended &quot;to support a reasonable subset of Org mode&quot;. There is also &lt;a href=&quot;https://ox-hugo.scripter.co&quot;&gt;ox-hugo&lt;/a&gt;, an Org exporter to Hugo Markdown, but I have not tried it yet.&lt;/p&gt;
&lt;p&gt;(Update 2024-10-26: I&#39;ve been using Markdown also. Org mode is nice, but Markdown is more common, and since I&#39;ve been using Markdown in other places where org mode can&#39;t be used, I find it easier to stick with one syntax. Hugo handles both fine, so there&#39;s no need to convert files.)&lt;/p&gt;
&lt;p&gt;I&#39;m not sure how much I will blog, but probably not a lot. My main motivation for starting a blog is to write down things I have learned. Hopefully some of what I write will be helpful to others, but I also want something for myself to refresh my memory later. I have learned a lot from people that write down things they have learned, whether they are experts or not. I want to do my part to keep that tradition strong.&lt;/p&gt;
&lt;p&gt;Of course, it&#39;s also possible there will be long periods of silence occasionally interrupted by posts about my intentions to start blogging again. ;)&lt;/p&gt;
&lt;p&gt;(Update 2023-11-24: I switched to using &lt;a href=&quot;https://srht.site/&quot;&gt;srht.site&lt;/a&gt; to host this. &lt;a href=&quot;https://git.sr.ht/~mrp/markpenner.space&quot;&gt;Source here&lt;/a&gt;, including the &lt;a href=&quot;https://git.sr.ht/~mrp/markpenner.space/tree/main/item/.build.yml&quot;&gt;.build.yml file&lt;/a&gt; to build and deploy the site using &lt;a href=&quot;https://builds.sr.ht/&quot;&gt;builds.sr.ht&lt;/a&gt;. Below is how I was hosting it at first, which I&#39;ll leave up in case it&#39;s useful to someone. I decided to save the money I was spending on a VPS since I wasn&#39;t using it for much.)&lt;/p&gt;
&lt;p&gt;I am using a &lt;a href=&quot;https://linode.com&quot;&gt;Linode&lt;/a&gt; VPS (virtual private server) to host the website (among other things). I have the source in a git repository with this post-receive hook to deploy the site after a successful &lt;code&gt;git push&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #4C4F69; background-color: #EFF1F5;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA76CB;font-style: italic;&quot;&gt;#!/bin/bash&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;GIT_REPO&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;/var/lib/git/markpenner.space.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;WORK_DIR&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;/tmp/work_dir&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;TARGET&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;/var/www/html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;BACKUP&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;/tmp/backup_html&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 style=&quot;color: #D20F39;font-style: italic;&quot;&gt;echo&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; &amp;quot;Post receive hook starting&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D20F39;font-style: italic;&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; -e&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 style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;rm&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; -rf&lt;/span&gt;&lt;span&gt; $WORK_DIR $BACKUP&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 style=&quot;color: #D20F39;font-style: italic;&quot;&gt;echo&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; &amp;quot;Making temporary directories.&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;mkdir&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; -p&lt;/span&gt;&lt;span&gt; $WORK_DIR $BACKUP&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 style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;rsync&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; -aqz&lt;/span&gt;&lt;span&gt; $TARGET&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;/&lt;/span&gt;&lt;span&gt; $BACKUP&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D20F39;font-style: italic;&quot;&gt;trap&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; &amp;quot;echo &amp;#39;A problem occurred.  Reverting to backup.&amp;#39;; rsync -aqz --del &lt;/span&gt;&lt;span&gt;$BACKUP&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;/ &lt;/span&gt;&lt;span&gt;$TARGET&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;; rm -rf &lt;/span&gt;&lt;span&gt;$WORK_DIR $BACKUP&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;&amp;quot; EXIT&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 style=&quot;color: #D20F39;font-style: italic;&quot;&gt;echo&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; &amp;quot;Pulling into temporary directory.&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; clone&lt;/span&gt;&lt;span&gt; $GIT_REPO $WORK_DIR&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 style=&quot;color: #D20F39;font-style: italic;&quot;&gt;echo&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; &amp;quot;Removing existing site.&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;rm&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; -rf&lt;/span&gt;&lt;span&gt; $TARGET&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;/&lt;/span&gt;&lt;span&gt;*&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 style=&quot;color: #D20F39;font-style: italic;&quot;&gt;echo&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; &amp;quot;building new site&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;hugo&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; -s&lt;/span&gt;&lt;span&gt; $WORK_DIR&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; -d&lt;/span&gt;&lt;span&gt; $TARGET&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 style=&quot;color: #D20F39;font-style: italic;&quot;&gt;echo&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; &amp;quot;Removing temporary directories.&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;rm&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; -rf&lt;/span&gt;&lt;span&gt; $WORK_DIR $BACKUP&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D20F39;font-style: italic;&quot;&gt;trap&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; - EXIT&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
  </channel>
</rss>
