Repository navigation
Added
-
Added the
gcalbackend, calendula over the Google Calendar API v3 through io-gcal, behind agcalfeature and an[accounts.<name>.gcal]block carrying a bearerauth.token.Google's CalDAV bridge is crippled, so a Google account used to be read-mostly with no calendar creation. Calendars are now writable, a date range is pushed down as
timeMinandtimeMax, a listing walksnextPageTokenonly as far as the requested page, and an update honoursIf-Match.Google exposes no iCalendar, so the backend synthesizes the document and re-projects it on write. Managed fields go both ways, Google-only fields stay untouched by an update, provider-scoped ones are minted read-only as
X-GOOGLE-*, and every other line is stashed inextendedProperties.private.A zoned boundary carries the VTIMEZONE it references, so an item stands on its own as an .ics file and a series keeps expanding where it did across daylight-saving changes. The feature therefore carries a time zone database.
A recurring series and its modified instances are one item, the exceptions folded into the master's document under its UID with a RECURRENCE-ID, as RFC 4791 4.1 requires. Only VEVENT projects: a VTODO or VJOURNAL is refused by name.
-
Added the
gcalcommand family for what iCalendar cannot express:calendars,acl,free-busy,instances,move,quick-add,colorsandsettings.Push channels,
calendars.clearandtransferOwnershipare deliberately absent. -
Added the Microsoft Graph backend,
msgraph, in the default feature set, for Outlook and Microsoft 365 calendars.Events are synthesized as iCalendar both ways by io-msgraph's
icalfeature, and a recurring series with its exceptions is one item. Graph keeps no calendar description nor RGB colour, so naming either is refused, and only the series master is written back. -
Added the
pimdirbackend, calendula over a local pimdir store, behind apimdirfeature and an[accounts.<name>.pimdir]block carrying arootand an optionalaccount.It never owns the store. It reads through the lock-free reader, so a listing runs beside a sync, and stages each write as one queue action. Calendars come from the sync, so
calendar create,updateanddeleterefuse.The reader folds the pending queue over its reads, so a staged edit or deletion shows at once. A staged creation has no public id until the sync applies it, so it is counted rather than listed.
Reads are availability-aware: an item the sync has not downloaded still lists, and reading it reports "body not fetched". Its kind and date come from the typed summary row the store's owner derives (pimdir STORAGE Annex A).
Link ids, body hashes and summaries come from io-pimdir's own derivations, so an item calendula stages and the same item arriving through a sync are one item. Two resources whose bodies carry one UID both list, each under its own public id.
A store written by an earlier io-pimdir draft is refused, with a message asking to delete it and resync.
-
Added
pimdir status, reporting the account being read, every account the store groups collections under, how much of each calendar is downloaded, and how many creations are queued. -
Added a command family per component kind:
todo(VTODO) andjournal(VJOURNAL) joinevent(VEVENT), each withlist,read,build,create,updateanddelete.They are views over the same items, rendering the columns their kind is read by, and add no backend operation.
--fromand--tonarrow them locally, a server-side range being defined against a start and an end neither kind carries. VFREEBUSY and VTIMEZONE get no family. -
Added a composer to
build,createandupdate, opened by-i/--interactiveand configured byitem.composer.item.composeris a shell line or an argv list, at the top level and per account.--composer <COMMAND>overrides it for one run and requires-i, and--jsonrefuses to spawn one.It is spawned on a temporary iCalendar file with every stream inherited. Changed bytes are the item, an emptied or untouched file abandons the edit, and a non-zero exit is a failure.
What a composer wrote is validated against RFC 5545 first, a re-edit being offered on violations, and a composed item that cannot be written keeps its file and names it. An iCalendar given on the command line is never checked.
-
Added
buildto the four families, the create pipeline stopped before the write.It prints the iCalendar, reaches no backend and reads no configuration unless
-ineeds the composer.-o/--output <PATH>captures it,-iowning stdout, and an abandoned build prints nothing at exit 0. -
Added
event agenda, a cal(1)-style grid marking the days that carry an event, listed underneath by start.Every event at one instant is rendered under a single time column, and the
--jsonpayload maps each start to the labels starting at it. -
Added
--fromand--totoevent list(YYYY-MM-DD, both inclusive).They are pushed down as an RFC 4791
time-rangefilter on CalDAV and applied after parsing elsewhere, pimdir answering from the stored summary. A range lifts the default page-size cap. -
Added
-b/--backend, selecting which backend the shared commands target.autotakes the first configured one in priority order: vdir, pimdir, caldav, gcal, msgraph. -
Added the
json-schemacommand (aliasjson-schemas), printing the JSON Schema of a command's--jsonpayload, or writing one file per command under--dir. -
Added
gcal.alpn, the ALPN identifiers offered during the TLS handshake.Unset offers
http/1.1, and an empty list skips negotiation. Only rustls reads it.
Changed
-
BREAKING: switched every
--jsonpayload key to camelCase, and made the fourreadcommands answer{"contents"}rather than{"message"}.caldav discoverrenamedcalendar_home_settocalendarHomeSet, andvdir listrenameddisplay_nametodisplayName. The configuration stays kebab-case, and every command's plain-text output is unchanged. -
BREAKING: made item ids the resource names a CalDAV server returned, verbatim, io-webdav no longer appending nor stripping
.ics.It fixes read, update and delete addressing the wrong resource whenever an id did not end in
.ics, and a create returning an unusable id when the server named the resource itself. Scripts pinning a hand-built id need updating. -
BREAKING: rewrote the wizard on the Himalaya model as
calendula configure(aliaswizard), replacingaccount configure.One prompt takes an email address, a server URL or a local folder path, and its shape orients the rest. The account name is derived rather than prompted, and the account is tested before anything is emitted.
It is offered where nothing can happen without a configuration, and skipped under
--jsonor a non-terminal stdin. The account is written to a missing file, appended as plain text to an existing one so comments survive, or printed. -
BREAKING: renamed the remote backend from
webdavtocaldavacross the cargo feature, the subcommand and the config block.Only the io-webdav dependency keeps the WebDAV name.
-
BREAKING: dropped the io-calendar dependency, moving the cross-protocol layer into calendula, one adapter per protocol, as cardamum does.
io-calendar is frozen and pinned io-vdir 0.0.3 and io-webdav 0.0.1, so nothing below it could move while it stayed.
-
Renamed
completionsandmanualstocompletionandmanual, and the shared subcommands to the singularcalendar,eventanditem, the plurals staying as hidden aliases.The
gcalcommands mirroring a Calendar API resource keep that API's spelling and gained hidden singular aliases. -
Made the iCalendar of
createandupdatean optional trailing positional on all four families: a path, raw contents, or-for stdin.Both bail when given neither a source nor
-i. A create with no source mints its item, carrying aPRODID, aUID, aDTSTAMPand, on a VEVENT, aDTSTART.An update with no source starts from the stored item and sends the entity tag it read as
If-Match, unless--if-matchnames another.itemnames no component kind, so it mints nothing and says which families do. -
Made
createandupdateanswer a named output type rather than the printer'sMessage, an abandoned edit being an outcome they report.Both are untagged, so a write serializes as
{"id"}. -
Made the parent calendar an optional
-k/--calendarflag on every shared command instead of a positional, falling back to the newcalendar.default.calendar deletetakes it as a mandatory flag that never falls back. -
Deferred opening the backend connection to the first call that needs it.
A command running a composer holds none open while the editor is up, where a write after a long edit used to read a socket the server had closed. The four families resolve their account per subcommand, which lets
buildresolve none. -
Made
calendar createreport the identifier the backend assigned rather than the one asked for.They differ only on Google, which mints its own.
-
Made
caldav.servertake a bare authority (dav.example.org,domain:port) as well as a full URL, defaulting tohttps, as the sibling products spell the same key. -
Resolved each account credential once, so a
passorgpgentry shared by acaldavand agcalblock is unlocked once. -
Stopped writing a
default = falseline in wizard-generated accounts. -
Adopted ical-rs for iCalendar parsing, an item whose bytes do not parse being skipped rather than failing the listing.
-
Bumped the Pimalaya dependencies to their current releases, and turned the
pimdirfeature on by default.ical-rs 0.5, io-http 0.5, io-pimdir 0.5, io-vdir 0.2, io-webdav 0.5, pimalaya-cli 0.2, pimalaya-config 0.2, pimalaya-stream 0.3, and pimconf's successor io-pim-discovery 0.8.
-
Made a blocking stream that reports it is not ready retry for a minute before giving up (pimalaya-stream 0.3). Behaviour change.
A read deadline is armed at connect time. An exchange that used to end with a bare
Resource temporarily unavailable (os error 35), on macOS especially, now survives it. -
Turned
vendoredon by default and forwarded it to io-pimdir, socargo installbuilds SQLite from source and needs none on the machine.Drop it to link the system SQLite and save about 1 MB. It also vendors OpenSSL when
native-tlsis on. The Nix builds still link the store's SQLite. -
Replaced the direct comfy-table dependency with pimalaya-cli's re-export, moving it to v8.
table.presetkeeps its v7 positional string, mapped onto the new typed style. The truncation indicator changes from...to…. -
Included the affected calendar or collection id in every
calendar,caldavandvdirsuccess message. -
Documented each command's JSON output shape as the last paragraph of its
--help, and slimmed the README Usage section to a pointer. -
Relicensed from AGPL-3.0-only to dual MIT OR Apache-2.0.
Removed
- Removed
downloads-dir, read by nothing: calendula downloads no attachment.
Fixed
-
Fixed a component listing paginating before it narrowed by kind, so a page of
todo listcould come back empty.A calendar of thirty events and one todo answered
todo listwith an empty table. CalDAV now pushes the kind down as an RFC 4791comp-filterwith the window nested inside it, gcal answers a non-VEVENT kind without a round-trip, and pimdir reads the kind off the stored summary. -
Fixed a composed VEVENT carrying no DTSTART being sent, now refused.
RFC 5545 3.6.1 requires it unless the calendar specifies a METHOD, and SabreDAV answered HTTP 500 rather than naming it.
-
Fixed a whitespace-only source being handed to a backend as an empty body, now refused naming where it was read from.
-
Fixed CalDAV discovery settling on a URL with no DAV server behind it, such as a web page (io-pim-discovery 0.8).
Every candidate must now answer a
PROPFIND, and discovery fails otherwise rather than configure it. -
Fixed
--confignot reaching the wizard, the one path where a user is most likely to pass it. -
Fixed
tls.certnot expanding~and environment variables,cert = "~/ca.pem"looking for a literal./~/ca.pem.Every configured path is now expanded when it is read rather than at each use.
-
Fixed the pimdir backend refusing an unknown calendar without listing the ones it can take, a namespaced collection id being impossible to guess.
-
Fixed
completionwriting files to the working directory instead of printing the script to stdout, which broke every packaging helper capturing stdout.manualshares its shape, a positional list of command names and an optional--dir, socalendula manuals ./manbecomescalendula manual --dir ./man. -
Fixed a CalDAV calendar's time zone being dropped on create and update, io-webdav reading
calendar-timezonewhen listing but never writing it back. -
Fixed an item listing keeping a calendar's own multistatus self-entry, which iCloud echoes, as a bogus item.
-
Fixed the missing
Hostheader on HTTP/1.1 requests (io-http 0.2), which made servers answer 400 and broke the.well-knowndiscovery probe. -
Fixed
tls.certfor a self-signed server (pimalaya-stream 0.1.1), the certificate now being pinned to the server's leaf instead of registered as a trust anchor that rejected it.