If I have time (“ha ha ha ha”; I’m also doing this all via ssh from my phone) I’d like to see about making a Pkgsrc WIP package for this (since it’s quite a change from v2 it makes more sense to stick it in WIP rather than just upgrade the existing Pkgsrc package). On that note, I wonder if it’ll have to be split out into taskchampion and taskwarrior for Pkgsrc? I.e. so the new Rust taskchampion bit is built first and then the C++ taskwarrior bit includes that?

In the meantime I just built outside of Pkgsrc:

  1. Needed a small patch to build:

     diff --git a/CMakeLists.txt b/CMakeLists.txt
     index 25ed4d9eb..a644268ac 100644
     --- a/CMakeLists.txt
     +++ b/CMakeLists.txt
     @@ -65,7 +65,11 @@ SET (TASK_RCDIR "${TASK_DOCDIR}/rc" CACHE STRING "Installation directory for con
      SET (TASK_BINDIR  bin            CACHE STRING "Installation directory for the binary")
         
      # rust libs require these
     -set (TASK_LIBRARIES dl pthread)
     +if (NETBSD)
     +  set (TASK_LIBRARIES pthread)
     +else ()
     +  set (TASK_LIBRARIES dl pthread)
     +endif ()
         
      check_function_exists (timegm  HAVE_TIMEGM)
      check_function_exists (get_current_dir_name HAVE_GET_CURRENT_DIR_NAME)
    
  2. Needed this exporting: CARGO_HTTP_CAINFO=/usr/pkg/share/mozilla-rootcerts/cacert.pem
  3. And then a cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_RPATH_USE_LINK_PATH:BOOL=ON . to keep libuuid linked for the install; I am wondering if libuuid is even needed on NetBSD, probably not, but that can be an exercise for another day.
  4. The rest of it is per the INSTALL instructions.

I also updated my patch from ten years ago to fix recurring tasks for DST for v3:

diff --git a/src/recur.cpp b/src/recur.cpp
index d6bb47454..b11480245 100644
--- a/src/recur.cpp
+++ b/src/recur.cpp
@@ -53,6 +53,8 @@
 
 // Add a `time_t` delta to a Datetime, checking for and returning nullopt on integer overflow.
 std::optional<Datetime> checked_add_datetime(Datetime& base, time_t delta) {
+  Datetime recurrence_date;
+
   // Datetime::operator+ takes an integer delta, so check that range
   if (static_cast<time_t>(std::numeric_limits<int>::max()) < delta) {
     return std::nullopt;
@@ -62,6 +64,14 @@ std::optional<Datetime> checked_add_datetime(Datetime& base, time_t delta) {
   if (std::numeric_limits<time_t>::max() - base.toEpoch() < delta) {
     return std::nullopt;
   }
+  // Shift current to midday, to be safe of any DST changes, before calculating future date
+  // Then set back to correct hour
+  // Only do this if delta is a whole number of days
+  if (delta % 86400 == 0) {
+    recurrence_date = (Datetime (base.year(), base.month(), base.day()) + 43200) + delta;
+    return Datetime (recurrence_date.year(), recurrence_date.month(), recurrence_date.day()) + 3600 * base.hour() + 60 * base.minute() + base.second();
+  }
   return base + delta;
 }

It seems there maybe future plans to use timezones in tasks which would finally solve this properly so I guess since my approach is still a little hacky it’s not worth PR’ing (the idea didn’t get any traction in the last ten years anyway).