TLDR: Helped my father move. Then I shaved all the yaks. Fur everywhere. Very messy.
Because of the way holidays at ActiveState work, it’s very economical in terms of vacation days to take the last two weeks of the year off (Christmas and New year’s weeks). I had a fair bit of vacation left, so I decided to take the first week of the new year off as well, for a total of three weeks of vacation.
So what did I do with all that time?
Answer: Helped me father move, then wrote a lot of Rust and some Perl.
Helping My Father Move
My mother died at the beginning of September. She and my father had been living in Florida, but it didn’t make sense for my father to continue living there alone. My wife and I had been discussing moving to a new house in Minneapolis for a while, so my father suggested we find a place where we could all live. We were looking for either a duplex or a property with an ADU1. We found a perfect odd duplex2 very quickly. The sale closed on December 16. My father’s stuff from Florida arrived a few days later, and he moved in to his part of the duplex.
Unfortunately, because of COVID, we didn’t go down to Florida to help him prepare for the move. While he did sort through some of his stuff, his sorting could’ve been more aggressive, as he was moving from a large house with two people to a much smaller space with one person. The upshot is that he moved a ridiculous amount of stuff here, far more than could ever fit in his space. So we spent many hours going through it.
We still have a ridiculous number of boxes of stuff to give away in the main part of the house, along with an endless pile of cardboard and packing paper, but his unit in the duplex is looking great.
This made me even more enthusiastic about getting rid of tons of stuff before my wife and I move, which will happen later this year, after some renovations to our part of the duplex.
My Local COVID Tracker
I’ve posted about this a couple times already. I made an update to track more counties, as well as to add a graph showing the seven-day new case average per 10,000 people.
The new graph by population made it clear that the counties near me were doing worse than the state as a whole. The original graph, showing just the raw count of new cases, made it look like the state overall was worse than the nearby counties, when in fact I think the opposite is true.
Precious and My Yak Shaving Expedition
Switching DateTime to use Precious
for a few projects, including itself, but I wanted to try moving a Perl
project to it. I picked
DateTime for no particular
reason, other than that it’s something I’ve worked on for many years.
This is what led me down the yak shaving rabbit hole, to mix some metaphors.
First, I found some bugs with
precious and made a v0.0.7
release of it.
As I worked on switching DateTime to use
precious, I realized there was a
bootstrapping problem. With TidyAll, I can just specify TidyAll and any needed
plugins as develop phase prereqs for the distribution, making it easy for
others to install all the needed tools, like
perlcritic, and TidyAll itself.
precious isn’t on CPAN, nor is
omegasort. I did briefly consider going
down the whole Alien route, but quickly
discarded that idea. While depending on a notional
work fine for my Perl projects, it wouldn’t help for anything that’s not Perl.
precious, being a Rust project, produces a single statically
linked4 binary. Go programs like
omegasort are totally static, not even
linking libc. This will become more important later in my yak shaving
Just One Little Installer
So my next thought was to build a simple installer for
precious that could
be run using the very safe “pipe
curl output into an interpreter”
strategy. I quickly wrote an installer in Perl that would live in the
precious repo. I was using
fatpack, which is a great tool
for turning Perl programs into single-file executables, as long as all of its
dependencies are pure Perl.
But then I started thinking about
omegasort. Did I want to write a nearly
identical program to live in the
omegasort repo? And then do it again for my
next Rust or Go project? Plus there are lots of other useful tools that fall
in this “released as a single binary on GitHub” bucket, like
Just One(!) Installer
Then I had an idea. What if I wrote one installer for all these things? So I
made a little Perl distribution called
App-ugri, where “ugri” stood for
Universal GitHub Release Installer. I actually finished that before I realized
the critical flaw in my plan. Even though I could fatpack
ugri into a single
file so you could pipe
perl, what about Windows?
Then I remembered why I was creating this installer in the first place. It’s because of languages like Rust and Go that produce a single statically linked executable. The solution was pretty obvious. Write this installer in Rust.
“UBI” stands for Universal Binary Installer. I liked the pun here more than the original “ugri” name. Of course, by “universal binary installer” I mean it just installs single-file executables from GitHub project releases, so it’s not very universal (yet?).
Since I’d already written this once in Perl, writing a Rust version was mostly
pretty easy. The only wrinkle was that I had to learn a little bit about async
programming in Rust, because the GitHub API client I was using,
octocrab, is async. This was
something I’d been wanting to learn about anyway, so I welcomed the challenge.
There is a usable 0.0.2 release on the GitHub project’s releases page.
Of course, ubi has a bootstrapping problem. What do you install a universal
binary installer with? You
curl a script into
sh, of course5!
That looks like this:
That should work on Linux and macOS. But I would love some help with creating the equivalent PowerShell script for Windows. I also need to improve the release tooling to provide binaries for more systems.
Once you have
ubi installed, installing these tools is trivial:
But wait, there’s more yak!
Along the way, I also ended up working on my
bundle to to
make switching to
precious easier. So now my bundle will:
- Generate a
precious.tomlconfig file for any project which doesn’t yet have one, as long as there’s no
- Generate an extended test that runs
precious lint --alland makes sure there are no files that fail the linting checks.
- Generate a simple
dev-bin/install-xt-tool.shscript that installs
ubi, then uses that to install
- Generate a git hook script that uses
precious, along with a
git/setup.plscript to install that hook for the given repo.
- Update the
dist.inito always include an
authordepon the version of the bundle that is being run.
That last bullet point, about updating the
dist.ini file, came out of some
issues I found in trying to get precious tests passing in CI using my
for Azure Pipelines. I’ve written about those in the past as well. I ended
up making some improvements to the
helpers, so now
they’ll automatically run the
dev-bin/install-xt-tools.sh script before
running extended tests.
And when they’re building a tarball for any Perl distro where the name starts
with “Dist-Zilla”, they make sure to include the git checkout’s
@INC when running
dzil build. I assume that if you’re testing
dzil plugin or plugin bundle in CI, then you want to use said plugin or
bundle when generating the tarball for said plugin or bundle6.
The results of all of this can be seen in my PR to switch DateTime to
Other Random Bits
- I tweaked a PR for the CLDR project (Common Locale Data Repository) to fix a typo in one language’s datetime info.
- I submitted a PR to
octocrab to update its
dependencies so I could update the same deps in
- I made a new release of DateTime-Locale to add some more documentation.
- I almost started rewriting omegasort in Rust (just because I like it better than Go), but I managed to restrain myself. I might get back to this at some point, but I’m glad I worked on these other projects for now.
- I wrote this blog post.
Putting the Yaks to Bed
I wrapped this all up yesterday, more or less. I return to work on Monday, so my timing was pretty good.
Accessory Dwelling Unit - think of an apartment built over a garage. ↩︎
It’s not a normal duplex. Instead of a house split into two pieces, it’s an older three story house, built in 1915, with a newer, much smaller two story “apartment” attached to the back. ↩︎
Because TidyAll is in Perl, sorting plugins for it are just simple Perl classes. But
preciousonly invokes other executables, so I realized I needed a sorting tool soon after starting on
precious. I wanted to write the sorting tool in Rust but at the time I started, Rust had no support for Unicode collation, so I wrote it in Go instead. ↩︎
Except for libc. ↩︎
But it can install itself if you already have it installed. ↩︎
Does that sentence make any sense? I’ve lost track. There’s too much yak fur in here! ↩︎