Class: Pikuri::Thunderbird::Profile
- Inherits:
-
Object
- Object
- Pikuri::Thunderbird::Profile
- Defined in:
- lib/pikuri/thunderbird/profile.rb
Overview
Locates the active Thunderbird profile on disk and derives the paths
the mail/calendar backends read. Discovery never guesses: it either
resolves one profile unambiguously, raises DiscoveryError with a
fix, or (when Thunderbird isn't installed) returns nil so the
extension can simply omit the tools.
profile = Pikuri::Thunderbird::Profile.discover # => Profile or nil
profile&.gloda_path # …/global-messages-db.sqlite
profile&.gloda? # is the Gloda index present?
profile&.calendar_dir # …/calendar-data
Two install roots are probed, in this order: snap
(+~/snap/thunderbird/common/.thunderbird+, confirmed) and apt
(+~/.thunderbird+, recalled). Flatpak is out of scope. If both roots
hold a profiles.ini (a stale apt profile left behind by an apt→snap
migration is the common case), discovery raises rather than guess
which is live — the one-time fix (delete the obsolete root) beats a
liveness heuristic that guesses wrong exactly there. An explicit
profile_dir: override bypasses all of this.
Implementation details
Within a root, the active profile is the profiles.ini section with
Default=1 (or the sole profile when there's exactly one and none is
marked default); Path is resolved relative to the ini's directory
when IsRelative=1. The confirmed real-world ini has no [Install…]
sections (Firefox's per-install default mechanism), so the plain
Default=1 scan suffices.
Defined Under Namespace
Classes: DiscoveryError
Constant Summary collapse
- SNAP_ROOT =
Returns snap install root (confirmed on a live box).
File.('~/snap/thunderbird/common/.thunderbird')
- APT_ROOT =
Returns apt/deb install root (recalled).
File.('~/.thunderbird')
- ROOTS =
Returns probed roots in preference order.
{ snap: SNAP_ROOT, apt: APT_ROOT }.freeze
Instance Attribute Summary collapse
-
#dir ⇒ String
readonly
Absolute path of the resolved profile directory.
-
#variant ⇒ Symbol
readonly
:snap,:apt, or:override— which root this came from.
Class Method Summary collapse
-
.discover(profile_dir: nil) ⇒ Profile?
Discover the active profile, or return
nilwhen Thunderbird is not installed (noprofiles.iniunder any probed root).
Instance Method Summary collapse
-
#calendar_cache_db ⇒ String
Cached network-calendar store (CalDAV etc.).
-
#calendar_dbs ⇒ Array<String>
Existing calendar DBs (cache first — it holds the CalDAV events; local holds storage calendars).
-
#calendar_dir ⇒ String
The calendar stores directory.
-
#calendar_local_db ⇒ String
Local ("storage") calendar store.
-
#gloda? ⇒ Boolean
Whether the Gloda index exists (the mail backend's
available?gate). -
#gloda_path ⇒ String
Path to the Gloda full-text index DB.
- #initialize(dir:, variant:) ⇒ Profile constructor
-
#outbox_dir ⇒ String
A directory a snap-confined Thunderbird can read a hand-off file from, for the
.icsimport hand-off (CalendarCreate).
Constructor Details
#initialize(dir:, variant:) ⇒ Profile
85 86 87 88 |
# File 'lib/pikuri/thunderbird/profile.rb', line 85 def initialize(dir:, variant:) @dir = dir @variant = variant end |
Instance Attribute Details
#dir ⇒ String (readonly)
Returns absolute path of the resolved profile directory.
49 50 51 |
# File 'lib/pikuri/thunderbird/profile.rb', line 49 def dir @dir end |
#variant ⇒ Symbol (readonly)
Returns :snap, :apt, or :override — which root this
came from. Drives #outbox_dir (snap confinement differs).
53 54 55 |
# File 'lib/pikuri/thunderbird/profile.rb', line 53 def variant @variant end |
Class Method Details
.discover(profile_dir: nil) ⇒ Profile?
Discover the active profile, or return nil when Thunderbird is not
installed (no profiles.ini under any probed root).
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/pikuri/thunderbird/profile.rb', line 64 def self.discover(profile_dir: nil) return from_override(profile_dir) if profile_dir present = ROOTS.select { |_, root| File.file?(File.join(root, 'profiles.ini')) } return nil if present.empty? if present.size > 1 paths = present.values.join(' and ') raise DiscoveryError, "Found Thunderbird profiles under two roots (#{paths}). This usually " \ 'means a stale profile from an old install. Delete the obsolete root, ' \ 'or pass profile_dir: to pick one explicitly.' end variant, root = present.first new(dir: resolve_within(root), variant: variant) end |
Instance Method Details
#calendar_cache_db ⇒ String
Returns cached network-calendar store (CalDAV etc.).
101 |
# File 'lib/pikuri/thunderbird/profile.rb', line 101 def calendar_cache_db = File.join(calendar_dir, 'cache.sqlite') |
#calendar_dbs ⇒ Array<String>
Returns existing calendar DBs (cache first — it holds the CalDAV events; local holds storage calendars). Empty when the calendar-data dir has neither.
109 110 111 |
# File 'lib/pikuri/thunderbird/profile.rb', line 109 def calendar_dbs [calendar_cache_db, calendar_local_db].select { |p| File.file?(p) } end |
#calendar_dir ⇒ String
Returns the calendar stores directory.
98 |
# File 'lib/pikuri/thunderbird/profile.rb', line 98 def calendar_dir = File.join(@dir, 'calendar-data') |
#calendar_local_db ⇒ String
Returns local ("storage") calendar store.
104 |
# File 'lib/pikuri/thunderbird/profile.rb', line 104 def calendar_local_db = File.join(calendar_dir, 'local.sqlite') |
#gloda? ⇒ Boolean
Returns whether the Gloda index exists (the mail backend's
available? gate).
95 |
# File 'lib/pikuri/thunderbird/profile.rb', line 95 def gloda? = File.file?(gloda_path) |
#gloda_path ⇒ String
Returns path to the Gloda full-text index DB.
91 |
# File 'lib/pikuri/thunderbird/profile.rb', line 91 def gloda_path = File.join(@dir, 'global-messages-db.sqlite') |
#outbox_dir ⇒ String
A directory a snap-confined Thunderbird can read a hand-off file from,
for the .ics import hand-off (CalendarCreate). Snap's home
interface blocks hidden $HOME dirs (so the ~/.cache snapshot dir is
unreadable by the confined app — see DESIGN.md § "Platform
confinement"); we stage instead in the variant's own readable root: the
snap-owned data area for :snap (readable regardless of the dotfile
rule), the unconfined profile dir for +:apt+/+:override+. The caller
creates the dir and reaps the file.
124 125 126 127 |
# File 'lib/pikuri/thunderbird/profile.rb', line 124 def outbox_dir base = @variant == :snap ? File.dirname(SNAP_ROOT) : @dir File.join(base, 'pikuri-outbox') end |