Class: Fontist::SystemIndexFontCollection
- Inherits:
-
Lutaml::Model::Collection
- Object
- Lutaml::Model::Collection
- Fontist::SystemIndexFontCollection
- Includes:
- Utils::Locking
- Defined in:
- lib/fontist/system_index.rb
Constant Summary collapse
- INDEX_REBUILD_THRESHOLD =
Don’t rebuild index more frequently than this (in seconds)
30 * 60
- ALLOWED_KEYS =
%i[path full_name family_name type].freeze
- OPTIONAL_KEYS =
Optional metadata keys for optimization (not required for validity)
%i[file_size file_mtime].freeze
Instance Attribute Summary collapse
-
#path ⇒ Object
Returns the value of attribute path.
-
#paths_loader ⇒ Object
Returns the value of attribute paths_loader.
Class Method Summary collapse
Instance Method Summary collapse
- #build(forced: false, verbose: false, stats: nil) ⇒ Object
-
#check_index ⇒ Object
Check if the content has all required keys.
-
#disable_read_only_mode ⇒ Object
Disable read-only mode so future ‘index` calls go through `index_changed?` again.
- #find(font, style, format_spec: nil) ⇒ Object
- #index ⇒ Object
- #index_changed? ⇒ Boolean
-
#mark_verified! ⇒ Object
Mark this index as verified, skipping future index_changed? checks Used after successfully loading the index from file.
-
#read_only_mode ⇒ Object
Enable read-only mode for operations that don’t need index rebuilding This is used during manifest compilation to avoid expensive index checks.
- #rebuild(verbose: false, stats: nil) ⇒ Object
-
#reset_verification! ⇒ Object
Reset verification flag (for testing or forcing re-check).
- #set_content(path, paths_loader) ⇒ Object
-
#set_path(path) ⇒ Object
30 minutes.
- #set_path_loader(paths_loader) ⇒ Object
- #to_file(path) ⇒ Object
- #update(verbose: false, stats: nil) ⇒ Object
Methods included from Utils::Locking
Instance Attribute Details
#path ⇒ Object
Returns the value of attribute path.
146 147 148 |
# File 'lib/fontist/system_index.rb', line 146 def path @path end |
#paths_loader ⇒ Object
Returns the value of attribute paths_loader.
146 147 148 |
# File 'lib/fontist/system_index.rb', line 146 def paths_loader @paths_loader end |
Class Method Details
.from_file(path:, paths_loader:) ⇒ Object
169 170 171 172 173 174 |
# File 'lib/fontist/system_index.rb', line 169 def self.from_file(path:, paths_loader:) # If the file does not exist, return a new collection return new.set_content(path, paths_loader) unless File.exist?(path) from_yaml(File.read(path)).set_content(path, paths_loader) end |
Instance Method Details
#build(forced: false, verbose: false, stats: nil) ⇒ Object
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 |
# File 'lib/fontist/system_index.rb', line 329 def build(forced: false, verbose: false, stats: nil) if forced return rebuild_with_lock(verbose: verbose, stats: stats) end previous_index = load_index updated_fonts = update if changed?(updated_fonts, previous_index.fonts || []) # Store the updated fonts so we don't need to call update again @pending_fonts = updated_fonts.fonts rebuild_with_lock(verbose: verbose, stats: stats) end self end |
#check_index ⇒ Object
Check if the content has all required keys
189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/fontist/system_index.rb', line 189 def check_index Fontist.formulas_repo_path_exists! Array(fonts).each do |font| missing_keys = ALLOWED_KEYS.reject do |key| font.send(key) end raise_font_index_corrupted(font, missing_keys) if missing_keys.any? end end |
#disable_read_only_mode ⇒ Object
Disable read-only mode so future ‘index` calls go through `index_changed?` again. Paired with `read_only_mode` to scope the optimization to a single block (see Manifest.with_performance_optimizations).
264 265 266 267 |
# File 'lib/fontist/system_index.rb', line 264 def disable_read_only_mode @read_only_mode = false self end |
#find(font, style, format_spec: nil) ⇒ Object
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/fontist/system_index.rb', line 206 def find(font, style, format_spec: nil) current_fonts = index return nil if current_fonts.nil? || current_fonts.empty? if style.nil? found_fonts = current_fonts.select do |file| file.family_name&.casecmp?(font) end else found_fonts = current_fonts.select do |file| file.family_name&.casecmp?(font) && file.type&.casecmp?(style) end end # Apply format filtering if specified if format_spec&.has_constraints? && found_fonts require_relative "format_matcher" matcher = FormatMatcher.new(format_spec) found_fonts = matcher.filter_indexed_fonts(found_fonts) end found_fonts.empty? ? nil : found_fonts end |
#index ⇒ Object
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/fontist/system_index.rb', line 231 def index # Fast path: if read_only mode is set, skip index_changed? check entirely. # But we still need to build on first access — treat an empty fonts list # the same as nil, since Lutaml initializes `instances :fonts` to `[]` # rather than nil when the on-disk index file is absent. if @read_only_mode && !fonts.nil? && !fonts.empty? return fonts end return fonts unless index_changed? # Notify user about index rebuild for large collections paths = @paths_loader&.call || [] if (paths.size > 100) && !@verbose Fontist.ui.say("Building font index (#{paths.size} fonts found, this may take a while...)") end build check_index fonts end |
#index_changed? ⇒ Boolean
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
# File 'lib/fontist/system_index.rb', line 269 def index_changed? return true if fonts.nil? || fonts.empty? return false if @index_check_done # Skip if already verified in this session # Quick check: if index was scanned recently, trust it if recently_scanned? Fontist.ui.debug("System index scanned #{time_since_scan} seconds ago, skipping check") @index_check_done = true return false end # Quick check: if directories haven't changed, trust the index if directories_unchanged? Fontist.ui.debug("Font directories unchanged, skipping full scan") @index_check_done = true # Update last scan time to extend validity self.last_scan_time = Time.now.to_i return false end # At this point we need to do a full scan Fontist.ui.debug("Font directories changed or stale, performing full scan") # Cache the paths loader results to avoid repeated Dir.glob calls @cached_current_paths ||= @paths_loader&.call&.sort&.uniq || [] excluded_paths_in_current = @cached_current_paths.select do |path| excluded?(path) end changed = @cached_current_paths != (font_paths + excluded_paths_in_current).uniq.sort # Mark as verified if unchanged, so we don't check again in this session @index_check_done = true unless changed changed end |
#mark_verified! ⇒ Object
Mark this index as verified, skipping future index_changed? checks Used after successfully loading the index from file
310 311 312 313 |
# File 'lib/fontist/system_index.rb', line 310 def mark_verified! @index_check_done = true self end |
#read_only_mode ⇒ Object
Enable read-only mode for operations that don’t need index rebuilding This is used during manifest compilation to avoid expensive index checks
256 257 258 259 |
# File 'lib/fontist/system_index.rb', line 256 def read_only_mode @read_only_mode = true self end |
#rebuild(verbose: false, stats: nil) ⇒ Object
346 347 348 |
# File 'lib/fontist/system_index.rb', line 346 def rebuild(verbose: false, stats: nil) build(forced: true, verbose: verbose, stats: stats) end |
#reset_verification! ⇒ Object
Reset verification flag (for testing or forcing re-check)
316 317 318 319 320 |
# File 'lib/fontist/system_index.rb', line 316 def reset_verification! @index_check_done = false @cached_current_paths = nil self end |
#set_content(path, paths_loader) ⇒ Object
176 177 178 179 180 181 |
# File 'lib/fontist/system_index.rb', line 176 def set_content(path, paths_loader) tap do |content| content.set_path(path) content.set_path_loader(paths_loader) end end |
#set_path(path) ⇒ Object
30 minutes
161 162 163 |
# File 'lib/fontist/system_index.rb', line 161 def set_path(path) @path = path end |
#set_path_loader(paths_loader) ⇒ Object
165 166 167 |
# File 'lib/fontist/system_index.rb', line 165 def set_path_loader(paths_loader) @paths_loader = paths_loader end |
#to_file(path) ⇒ Object
201 202 203 204 |
# File 'lib/fontist/system_index.rb', line 201 def to_file(path) FileUtils.mkdir_p(File.dirname(path)) File.write(path, to_yaml) end |
#update(verbose: false, stats: nil) ⇒ Object
322 323 324 325 326 327 |
# File 'lib/fontist/system_index.rb', line 322 def update(verbose: false, stats: nil) tap do |col| col.fonts = detect_paths(@paths_loader&.call || [], verbose: verbose, stats: stats) end end |