fontist 3.0.14 → 3.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/fontist/formula.rb +17 -5
- data/lib/fontist/from_file_cache.rb +52 -0
- data/lib/fontist/indexes/base_font_collection_index.rb +4 -0
- data/lib/fontist/indexes/fontist_index.rb +9 -2
- data/lib/fontist/indexes/index_mixin.rb +10 -5
- data/lib/fontist/version.rb +1 -1
- data/lib/fontist.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3871228b469c6c8ee43f6bd04d6b9726feddac6fb2245f3f2bf5533b05a2baf9
|
|
4
|
+
data.tar.gz: 9e6d136e1ceaa16dd7a3907fe346bbc0a90f46a51458334a5192b5a2dea085e9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a201906009471c3844a708096fea687db8aa5a8eb56efc3e13076580dfefd1fea95e12edbbe2707928f5b3ed77db326a5147bf6e043965033fc5b27586166dc2
|
|
7
|
+
data.tar.gz: b4ff402ff006a766f1daee41ffbed825f826b24c88997e9ea92a91c435fcf88545ffdf921f7091371a247b489a2dc4d0ee92faad6b11a1dfae5f2967ddcd038d
|
data/lib/fontist/formula.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require "lutaml/model"
|
|
2
|
+
require "parallel"
|
|
2
3
|
require_relative "format_matcher"
|
|
3
4
|
require "git"
|
|
4
5
|
|
|
@@ -100,9 +101,14 @@ module Fontist
|
|
|
100
101
|
end
|
|
101
102
|
|
|
102
103
|
def all
|
|
103
|
-
|
|
104
|
+
paths = Dir[Fontist.formulas_path.join("**/*.yml").to_s]
|
|
105
|
+
|
|
106
|
+
# Parsing thousands of formula files dominates index rebuilds;
|
|
107
|
+
# worker threads overlap the libyaml C parse, which releases
|
|
108
|
+
# the GVL
|
|
109
|
+
formulas = Parallel.map(paths) do |path|
|
|
104
110
|
Formula.from_file(path)
|
|
105
|
-
end
|
|
111
|
+
end.compact
|
|
106
112
|
|
|
107
113
|
FormulaCollection.new(formulas)
|
|
108
114
|
end
|
|
@@ -181,9 +187,15 @@ module Fontist
|
|
|
181
187
|
|
|
182
188
|
content = File.read(path)
|
|
183
189
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
190
|
+
# Parsing a formula costs ~10-20ms and the same formula is
|
|
191
|
+
# re-read on every lookup, so the parsed instance is memoized
|
|
192
|
+
# (mtime-validated) and shared between callers; treat as
|
|
193
|
+
# read-only
|
|
194
|
+
formula = Fontist::FromFileCache.memoize(path) { from_yaml(content) }
|
|
195
|
+
|
|
196
|
+
formula.tap do |f|
|
|
197
|
+
f.path = path
|
|
198
|
+
f.name = titleize(f.key_from_path) if f.name.nil?
|
|
187
199
|
end
|
|
188
200
|
rescue Lutaml::Model::Error, TypeError, ArgumentError,
|
|
189
201
|
Psych::BadAlias, Psych::SyntaxError => e
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Fontist
|
|
2
|
+
# Thread-safe, mtime-validated memoization for parsed YAML artifacts
|
|
3
|
+
# (formula index, formula files), which cost hundreds of milliseconds to
|
|
4
|
+
# parse and are re-read on every font lookup.
|
|
5
|
+
#
|
|
6
|
+
# Returned instances are shared between all callers and must be treated
|
|
7
|
+
# as read-only. Entries re-resolve automatically when the file's mtime
|
|
8
|
+
# changes (e.g. after `fontist update` rewrites the formulas repo).
|
|
9
|
+
module FromFileCache
|
|
10
|
+
def self.memoize(path)
|
|
11
|
+
mtime = File.mtime(path)
|
|
12
|
+
|
|
13
|
+
hit = current_value(path, mtime)
|
|
14
|
+
return hit if hit
|
|
15
|
+
|
|
16
|
+
# Parse without holding the lock so parallel readers (e.g.
|
|
17
|
+
# Formula.all over worker threads) overlap; concurrent misses on
|
|
18
|
+
# the same path may duplicate work but write identical values
|
|
19
|
+
value = yield
|
|
20
|
+
|
|
21
|
+
store(path, mtime, value)
|
|
22
|
+
|
|
23
|
+
value
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.clear
|
|
27
|
+
mutex.synchronize { cache.clear }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.current_value(path, mtime)
|
|
31
|
+
hit = mutex.synchronize { cache[path] }
|
|
32
|
+
hit&.fetch(:mtime, nil) == mtime ? hit[:value] : nil
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.store(path, mtime, value)
|
|
36
|
+
mutex.synchronize do
|
|
37
|
+
existing = cache[path]
|
|
38
|
+
if existing.nil? || existing[:mtime] != mtime
|
|
39
|
+
cache[path] = { mtime: mtime, value: value }
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.mutex
|
|
45
|
+
@mutex ||= Mutex.new
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.cache
|
|
49
|
+
@cache ||= {}
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -132,6 +132,10 @@ module Fontist
|
|
|
132
132
|
# @param verbose [Boolean] Show detailed progress information
|
|
133
133
|
# @return [void]
|
|
134
134
|
def rebuild(verbose: false)
|
|
135
|
+
# A rebuild is an explicit request for a fresh scan, so any
|
|
136
|
+
# memoized font_paths must be dropped first
|
|
137
|
+
reset_scan_cache
|
|
138
|
+
|
|
135
139
|
collection.rebuild(verbose: verbose)
|
|
136
140
|
end
|
|
137
141
|
|
|
@@ -37,10 +37,17 @@ module Fontist
|
|
|
37
37
|
# Uses case-insensitive glob patterns that work on all platforms,
|
|
38
38
|
# including Linux where File::FNM_CASEFOLD is ignored
|
|
39
39
|
#
|
|
40
|
+
# Delegates to the memoized fontist-repo scan on SystemFont; the
|
|
41
|
+
# memo is invalidated through reset_scan_cache when fonts are
|
|
42
|
+
# installed or removed mid-process
|
|
43
|
+
#
|
|
40
44
|
# @return [Array<String>] Array of font file paths
|
|
41
45
|
def font_paths
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
SystemFont.fontist_font_paths
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def reset_scan_cache
|
|
50
|
+
SystemFont.reset_fontist_font_paths_cache
|
|
44
51
|
end
|
|
45
52
|
end
|
|
46
53
|
end
|
|
@@ -49,12 +49,13 @@ module Fontist
|
|
|
49
49
|
|
|
50
50
|
file_content = File.read(file_path).strip
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return new
|
|
55
|
-
end
|
|
52
|
+
# Return empty collection for empty index files
|
|
53
|
+
return new if file_content.empty? || file_content == "---"
|
|
56
54
|
|
|
57
|
-
|
|
55
|
+
# Parsing the index YAML costs hundreds of milliseconds and
|
|
56
|
+
# happens on every font lookup, so the parsed instance is
|
|
57
|
+
# memoized (mtime-validated) and shared between callers
|
|
58
|
+
Fontist::FromFileCache.memoize(file_path) { from_yaml(file_content) }
|
|
58
59
|
end
|
|
59
60
|
|
|
60
61
|
def rebuild
|
|
@@ -67,6 +68,10 @@ module Fontist
|
|
|
67
68
|
end
|
|
68
69
|
|
|
69
70
|
def reset_cache
|
|
71
|
+
# Drop the memoized parsed instance along with the index file,
|
|
72
|
+
# to force a fresh parse on next access
|
|
73
|
+
Fontist::FromFileCache.clear
|
|
74
|
+
|
|
70
75
|
# Delete the index file to force rebuild on next access
|
|
71
76
|
# This is important for tests to ensure clean state
|
|
72
77
|
FileUtils.rm_f(path)
|
data/lib/fontist/version.rb
CHANGED
data/lib/fontist.rb
CHANGED
|
@@ -7,6 +7,7 @@ require "lutaml/model"
|
|
|
7
7
|
require_relative "fontist/errors"
|
|
8
8
|
require_relative "fontist/version"
|
|
9
9
|
require_relative "fontist/cache"
|
|
10
|
+
require_relative "fontist/from_file_cache"
|
|
10
11
|
require_relative "fontist/memoizable"
|
|
11
12
|
require_relative "fontist/path_scanning"
|
|
12
13
|
require_relative "fontist/utils"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fontist
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.0.
|
|
4
|
+
version: 3.0.16
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-11-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: down
|
|
@@ -375,6 +375,7 @@ files:
|
|
|
375
375
|
- lib/fontist/formula.rb
|
|
376
376
|
- lib/fontist/formula_picker.rb
|
|
377
377
|
- lib/fontist/formula_suggestion.rb
|
|
378
|
+
- lib/fontist/from_file_cache.rb
|
|
378
379
|
- lib/fontist/google_import_source.rb
|
|
379
380
|
- lib/fontist/helpers.rb
|
|
380
381
|
- lib/fontist/import.rb
|