fontist 3.0.36 → 3.0.37
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/.github/workflows/release.yml +10 -0
- data/.github/workflows/tebako-pack.yml +219 -45
- data/README.adoc +50 -0
- data/docs/.vitepress/config.ts +1 -1
- data/lib/fontist/cli.rb +9 -1
- data/lib/fontist/font.rb +21 -3
- data/lib/fontist/system_index.rb +4 -1
- data/lib/fontist/validation.rb +1 -1
- data/lib/fontist/validator.rb +1 -2
- data/lib/fontist/version.rb +1 -1
- data/packaging/nfpm.yaml +33 -0
- data/script/tebako/entry.rb +90 -0
- data/script/tebako/package-smoke.sh +33 -0
- data/script/tebako/package.sh +23 -0
- data/script/tebako/press.sh +36 -0
- data/script/tebako/smoke.sh +25 -0
- data/script/tebako/stage.sh +39 -0
- metadata +9 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 85b1409d941968bcf69c2058ab3e3ffac4138279bf6c262d670206590dd8e557
|
|
4
|
+
data.tar.gz: f025af9d9214504168b1612f7f42f3142afdadb9112e9283022fe92378665000
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6c13e6cca540bd6f5e2ed3bd203bad3b4dad7db56824d34e36b511331b6a9bd5b5178ecf7fc6717318d54981950c33536ae3dfc6eafc82e4ceaf771f3b08fbdb
|
|
7
|
+
data.tar.gz: f1a3542fcda412f62e763cb38d9484028ddc65585eba3d6c9cb982eea8ef80656672769fc898a5b4266ef7419adadcf7e592200f4d7c8c9845505ddf13ec4f58
|
|
@@ -28,3 +28,13 @@ jobs:
|
|
|
28
28
|
next_version: ${{ github.event.inputs.next_version }}
|
|
29
29
|
secrets:
|
|
30
30
|
rubygems-api-key: ${{ secrets.FONTIST_CI_RUBYGEMS_API_KEY }}
|
|
31
|
+
|
|
32
|
+
# Self-contained executables and .deb/.rpm packages for the new version,
|
|
33
|
+
# attached to its GitHub Release (fontist/fontist#463).
|
|
34
|
+
packages:
|
|
35
|
+
needs: release
|
|
36
|
+
permissions:
|
|
37
|
+
contents: write
|
|
38
|
+
uses: ./.github/workflows/tebako-pack.yml
|
|
39
|
+
with:
|
|
40
|
+
publish: true
|
|
@@ -1,65 +1,239 @@
|
|
|
1
1
|
name: tebako-pack
|
|
2
2
|
|
|
3
|
+
# Packs fontist into one self-contained executable per platform with
|
|
4
|
+
# tebako v2, wraps the Linux ones into .deb/.rpm packages, checks both on
|
|
5
|
+
# machines with no Ruby, and attaches them to the GitHub Release when given
|
|
6
|
+
# a tag.
|
|
7
|
+
|
|
3
8
|
on:
|
|
4
|
-
|
|
5
|
-
|
|
9
|
+
# Called by release.yml once the gem is out. Its releases are created with
|
|
10
|
+
# GITHUB_TOKEN, and GitHub starts no workflow from such an event, so a
|
|
11
|
+
# `release: published` trigger here would never fire.
|
|
12
|
+
workflow_call:
|
|
13
|
+
inputs:
|
|
14
|
+
publish:
|
|
15
|
+
type: boolean
|
|
16
|
+
default: true
|
|
6
17
|
workflow_dispatch:
|
|
18
|
+
inputs:
|
|
19
|
+
tag:
|
|
20
|
+
description: Release tag to build and attach to (empty = build only)
|
|
21
|
+
required: false
|
|
22
|
+
default: ''
|
|
23
|
+
pull_request:
|
|
24
|
+
paths:
|
|
25
|
+
- .github/workflows/tebako-pack.yml
|
|
26
|
+
- script/tebako/**
|
|
27
|
+
- packaging/**
|
|
7
28
|
|
|
8
29
|
permissions:
|
|
9
30
|
contents: read
|
|
10
|
-
packages: write
|
|
11
31
|
|
|
12
32
|
concurrency:
|
|
13
|
-
group: '${{ github.workflow }}-${{ github.
|
|
33
|
+
group: '${{ github.workflow }}-${{ github.head_ref || github.ref_name }}'
|
|
14
34
|
cancel-in-progress: true
|
|
15
35
|
|
|
16
36
|
env:
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
# has better performance
|
|
23
|
-
TEBAKO_RUBY_VER: 3.1.4
|
|
37
|
+
# Ruby the packed fontist runs on: a version tebako ships a runtime for
|
|
38
|
+
# (tebako press rejects the rest).
|
|
39
|
+
PACKAGE_RUBY_VERSION: 3.3.12
|
|
40
|
+
TEBAKO_VERSION: 2.8.68
|
|
41
|
+
NFPM_VERSION: 2.48.0
|
|
24
42
|
|
|
25
43
|
jobs:
|
|
44
|
+
resolve:
|
|
45
|
+
name: resolve tag
|
|
46
|
+
runs-on: ubuntu-24.04
|
|
47
|
+
outputs:
|
|
48
|
+
tag: ${{ steps.tag.outputs.tag }}
|
|
49
|
+
steps:
|
|
50
|
+
# After release.yml the default branch carries the released version.
|
|
51
|
+
- uses: actions/checkout@v4
|
|
52
|
+
with:
|
|
53
|
+
ref: ${{ github.event.repository.default_branch }}
|
|
54
|
+
|
|
55
|
+
- id: tag
|
|
56
|
+
env:
|
|
57
|
+
GH_TOKEN: ${{ github.token }}
|
|
58
|
+
CALLED: ${{ github.event_name != 'workflow_dispatch' && github.event_name != 'pull_request' && inputs.publish }}
|
|
59
|
+
INPUT_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || '' }}
|
|
60
|
+
run: |
|
|
61
|
+
if [ "$CALLED" = true ]; then
|
|
62
|
+
tag="v$(sed -n 's/.*VERSION = "\(.*\)".*/\1/p' lib/fontist/version.rb)"
|
|
63
|
+
else
|
|
64
|
+
tag="$INPUT_TAG"
|
|
65
|
+
fi
|
|
66
|
+
if [ -n "$tag" ]; then
|
|
67
|
+
# Only a version tag that is a published release of this repo.
|
|
68
|
+
if ! printf '%s' "$tag" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
|
|
69
|
+
echo "not a release tag: $tag" >&2
|
|
70
|
+
exit 1
|
|
71
|
+
fi
|
|
72
|
+
gh release view "$tag" --repo "$GITHUB_REPOSITORY" --json tagName >/dev/null
|
|
73
|
+
fi
|
|
74
|
+
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
|
75
|
+
echo "building ${tag:-$GITHUB_SHA}"
|
|
76
|
+
|
|
26
77
|
pack:
|
|
27
|
-
name:
|
|
78
|
+
name: pack ${{ matrix.name }}
|
|
79
|
+
needs: resolve
|
|
28
80
|
runs-on: ${{ matrix.os }}
|
|
29
81
|
strategy:
|
|
30
82
|
fail-fast: false
|
|
31
|
-
# macos-11 runner is deadly slow because brew is not supported on this version anymore
|
|
32
|
-
# so it is practically impossible to use it for tests anymore
|
|
33
83
|
matrix:
|
|
34
|
-
|
|
84
|
+
include:
|
|
85
|
+
# Linux is packed on the oldest runner so the result runs on older
|
|
86
|
+
# glibc distros too.
|
|
87
|
+
- { os: ubuntu-22.04, triplet: linux-gnu-x86_64, name: linux-x86_64 }
|
|
88
|
+
- { os: ubuntu-22.04-arm, triplet: linux-gnu-arm64, name: linux-arm64 }
|
|
89
|
+
- { os: macos-15, triplet: macos-arm64, name: macos-arm64 }
|
|
90
|
+
- { os: macos-15-intel, triplet: macos-x86_64, name: macos-x86_64 }
|
|
91
|
+
steps:
|
|
92
|
+
- uses: actions/checkout@v4
|
|
93
|
+
with:
|
|
94
|
+
fetch-depth: 0
|
|
95
|
+
|
|
96
|
+
# A release build packs the validated release tag, not the dispatching
|
|
97
|
+
# commit (release.yml bumps the version after this run's commit).
|
|
98
|
+
- name: Check out the release tag
|
|
99
|
+
if: needs.resolve.outputs.tag != ''
|
|
100
|
+
env:
|
|
101
|
+
TAG: ${{ needs.resolve.outputs.tag }}
|
|
102
|
+
run: git checkout --detach "refs/tags/$TAG"
|
|
103
|
+
|
|
104
|
+
- uses: ruby/setup-ruby@v1
|
|
105
|
+
with:
|
|
106
|
+
ruby-version: '3.3'
|
|
107
|
+
|
|
108
|
+
- name: Press
|
|
109
|
+
env:
|
|
110
|
+
GH_TOKEN: ${{ github.token }}
|
|
111
|
+
run: script/tebako/press.sh "${{ matrix.triplet }}" "out/fontist-${{ matrix.name }}"
|
|
112
|
+
|
|
113
|
+
# Uploaded before the smoke test so a failing binary can be fetched
|
|
114
|
+
# and inspected.
|
|
115
|
+
- uses: actions/upload-artifact@v4
|
|
116
|
+
with:
|
|
117
|
+
name: fontist-${{ matrix.name }}
|
|
118
|
+
path: out/fontist-${{ matrix.name }}
|
|
119
|
+
if-no-files-found: error
|
|
120
|
+
|
|
121
|
+
# Only the system directories and git stay on PATH, so the Ruby set up
|
|
122
|
+
# above is out of reach. (macOS keeps a system ruby in /usr/bin; the
|
|
123
|
+
# fresh distro containers in package-smoke are the no-Ruby-at-all
|
|
124
|
+
# check.) fontist's git gem needs git >= 2.43, newer than Apple's, so
|
|
125
|
+
# the runner's own git is kept.
|
|
126
|
+
- name: Smoke test without the build Ruby
|
|
127
|
+
run: |
|
|
128
|
+
git_dir="$(dirname "$(command -v git)")"
|
|
129
|
+
env -i HOME="$HOME" PATH="$git_dir:/usr/bin:/bin:/usr/sbin:/sbin" \
|
|
130
|
+
script/tebako/smoke.sh "out/fontist-${{ matrix.name }}"
|
|
131
|
+
|
|
132
|
+
packages:
|
|
133
|
+
name: deb and rpm
|
|
134
|
+
needs: [ resolve, pack ]
|
|
135
|
+
runs-on: ubuntu-24.04
|
|
35
136
|
steps:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
137
|
+
- uses: actions/checkout@v4
|
|
138
|
+
with:
|
|
139
|
+
fetch-depth: 0
|
|
140
|
+
|
|
141
|
+
# A release build packs the validated release tag, not the dispatching
|
|
142
|
+
# commit (release.yml bumps the version after this run's commit).
|
|
143
|
+
- name: Check out the release tag
|
|
144
|
+
if: needs.resolve.outputs.tag != ''
|
|
145
|
+
env:
|
|
146
|
+
TAG: ${{ needs.resolve.outputs.tag }}
|
|
147
|
+
run: git checkout --detach "refs/tags/$TAG"
|
|
148
|
+
|
|
149
|
+
- uses: actions/download-artifact@v4
|
|
150
|
+
with:
|
|
151
|
+
pattern: fontist-linux-*
|
|
152
|
+
path: out
|
|
153
|
+
merge-multiple: true
|
|
154
|
+
|
|
155
|
+
- name: Install nfpm
|
|
156
|
+
env:
|
|
157
|
+
GH_TOKEN: ${{ github.token }}
|
|
158
|
+
run: |
|
|
159
|
+
gh release download "v${NFPM_VERSION}" --repo goreleaser/nfpm --dir /tmp/nfpm \
|
|
160
|
+
--pattern "nfpm_${NFPM_VERSION}_Linux_x86_64.tar.gz" --pattern checksums.txt
|
|
161
|
+
(cd /tmp/nfpm && sha256sum --ignore-missing -c checksums.txt)
|
|
162
|
+
tar -xzf "/tmp/nfpm/nfpm_${NFPM_VERSION}_Linux_x86_64.tar.gz" -C /tmp/nfpm nfpm
|
|
163
|
+
sudo install /tmp/nfpm/nfpm /usr/local/bin/nfpm
|
|
164
|
+
|
|
165
|
+
- name: Build packages
|
|
166
|
+
run: |
|
|
167
|
+
script/tebako/package.sh amd64 out/fontist-linux-x86_64 pkg
|
|
168
|
+
script/tebako/package.sh arm64 out/fontist-linux-arm64 pkg
|
|
169
|
+
|
|
170
|
+
- uses: actions/upload-artifact@v4
|
|
171
|
+
with:
|
|
172
|
+
name: fontist-linux-packages
|
|
173
|
+
path: pkg/*
|
|
174
|
+
if-no-files-found: error
|
|
175
|
+
|
|
176
|
+
package-smoke:
|
|
177
|
+
name: install on ${{ matrix.image }} ${{ matrix.arch }}
|
|
178
|
+
needs: [ resolve, packages ]
|
|
179
|
+
runs-on: ${{ matrix.runner }}
|
|
180
|
+
container: ${{ matrix.image }}
|
|
181
|
+
strategy:
|
|
182
|
+
fail-fast: false
|
|
183
|
+
matrix:
|
|
184
|
+
# Distros whose git meets the git gem's >= 2.43; older ones refuse
|
|
185
|
+
# the package on its git dependency.
|
|
186
|
+
image: [ 'ubuntu:24.04', 'debian:13', 'fedora:latest', 'rockylinux:9' ]
|
|
187
|
+
arch: [ amd64 ]
|
|
188
|
+
runner: [ ubuntu-24.04 ]
|
|
189
|
+
include:
|
|
190
|
+
- { image: 'ubuntu:24.04', arch: arm64, runner: ubuntu-24.04-arm }
|
|
191
|
+
steps:
|
|
192
|
+
# Only the smoke scripts are used here, so the dispatching commit is
|
|
193
|
+
# enough (these containers have no git to check out a tag with).
|
|
194
|
+
- uses: actions/checkout@v4
|
|
195
|
+
|
|
196
|
+
- uses: actions/download-artifact@v4
|
|
197
|
+
with:
|
|
198
|
+
name: fontist-linux-packages
|
|
199
|
+
path: pkg
|
|
200
|
+
|
|
201
|
+
- name: Keep only this architecture
|
|
202
|
+
run: |
|
|
203
|
+
if [ "${{ matrix.arch }}" = amd64 ]; then
|
|
204
|
+
find pkg \( -name '*arm64*' -o -name '*aarch64*' \) -delete
|
|
205
|
+
else
|
|
206
|
+
find pkg \( -name '*amd64*' -o -name '*x86_64*' \) -delete
|
|
207
|
+
fi
|
|
208
|
+
ls -l pkg
|
|
209
|
+
|
|
210
|
+
- name: Install, use, remove
|
|
211
|
+
run: script/tebako/package-smoke.sh pkg
|
|
212
|
+
|
|
213
|
+
publish:
|
|
214
|
+
name: attach to release
|
|
215
|
+
if: needs.resolve.outputs.tag != ''
|
|
216
|
+
needs: [ resolve, pack, package-smoke ]
|
|
217
|
+
runs-on: ubuntu-24.04
|
|
218
|
+
permissions:
|
|
219
|
+
contents: write
|
|
220
|
+
steps:
|
|
221
|
+
- uses: actions/download-artifact@v4
|
|
222
|
+
with:
|
|
223
|
+
path: dist
|
|
224
|
+
merge-multiple: true
|
|
225
|
+
|
|
226
|
+
- name: Name executables by version and upload
|
|
227
|
+
env:
|
|
228
|
+
GH_TOKEN: ${{ github.token }}
|
|
229
|
+
TAG: ${{ needs.resolve.outputs.tag }}
|
|
230
|
+
run: |
|
|
231
|
+
version="${TAG#v}"
|
|
232
|
+
cd dist
|
|
233
|
+
for name in linux-x86_64 linux-arm64 macos-arm64 macos-x86_64; do
|
|
234
|
+
mv "fontist-$name" "fontist-$version-$name"
|
|
235
|
+
done
|
|
236
|
+
# Executables and .rpm files are fontist-*, .deb files fontist_*.
|
|
237
|
+
sha256sum fontist-* fontist_* > SHA256SUMS
|
|
238
|
+
gh release upload "$TAG" --repo "$GITHUB_REPOSITORY" --clobber \
|
|
239
|
+
fontist-* fontist_* SHA256SUMS
|
data/README.adoc
CHANGED
|
@@ -42,6 +42,56 @@ And then execute:
|
|
|
42
42
|
bundle install
|
|
43
43
|
----
|
|
44
44
|
|
|
45
|
+
=== Install without Ruby
|
|
46
|
+
|
|
47
|
+
Each release on the
|
|
48
|
+
https://github.com/fontist/fontist/releases[GitHub Releases] page has a
|
|
49
|
+
self-contained `fontist` executable. It does not need a Ruby installation.
|
|
50
|
+
Linux and macOS are supported.
|
|
51
|
+
|
|
52
|
+
Download the file for your system, check it, and make it executable. The
|
|
53
|
+
names are `fontist-<version>-linux-x86_64`, `-linux-arm64`, `-macos-arm64`
|
|
54
|
+
and `-macos-x86_64`.
|
|
55
|
+
|
|
56
|
+
[source,sh]
|
|
57
|
+
----
|
|
58
|
+
curl -LO https://github.com/fontist/fontist/releases/download/v<version>/fontist-<version>-linux-x86_64
|
|
59
|
+
curl -LO https://github.com/fontist/fontist/releases/download/v<version>/SHA256SUMS
|
|
60
|
+
sha256sum --ignore-missing -c SHA256SUMS # on macOS: shasum -a 256 -c --ignore-missing SHA256SUMS
|
|
61
|
+
chmod +x fontist-<version>-linux-x86_64
|
|
62
|
+
./fontist-<version>-linux-x86_64 version
|
|
63
|
+
----
|
|
64
|
+
|
|
65
|
+
The executables are not signed. On macOS, remove the quarantine flag before
|
|
66
|
+
the first run:
|
|
67
|
+
|
|
68
|
+
[source,sh]
|
|
69
|
+
----
|
|
70
|
+
xattr -d com.apple.quarantine ./fontist-<version>-macos-arm64
|
|
71
|
+
----
|
|
72
|
+
|
|
73
|
+
Each run prints a notice from the packager that the executable is unsigned.
|
|
74
|
+
It is harmless.
|
|
75
|
+
|
|
76
|
+
fontist needs git 2.43 or newer to fetch formulas. The git that ships with
|
|
77
|
+
macOS is older, so install a current one first (for example
|
|
78
|
+
`brew install git`).
|
|
79
|
+
|
|
80
|
+
On Debian and Ubuntu, install the `.deb` package. On Fedora and RHEL, install
|
|
81
|
+
the `.rpm` package. Both put `fontist` in `/usr/bin` and depend on git 2.43 or
|
|
82
|
+
newer, which Ubuntu 24.04, Debian 13, Fedora and RHEL 9 provide.
|
|
83
|
+
|
|
84
|
+
[source,sh]
|
|
85
|
+
----
|
|
86
|
+
sudo apt install ./fontist_<version>_amd64.deb
|
|
87
|
+
sudo dnf install ./fontist-<version>-1.x86_64.rpm
|
|
88
|
+
----
|
|
89
|
+
|
|
90
|
+
For ARM64, use `_arm64.deb` and `.aarch64.rpm`.
|
|
91
|
+
|
|
92
|
+
This build uses the same home directory as the gem (`~/.fontist`, or
|
|
93
|
+
`FONTIST_PATH` if set), so the two can be used side by side.
|
|
94
|
+
|
|
45
95
|
=== Fetch formulas
|
|
46
96
|
|
|
47
97
|
After installation, please fetch formulas via the `fontist` command:
|
data/docs/.vitepress/config.ts
CHANGED
|
@@ -248,7 +248,7 @@ export default defineConfig({
|
|
|
248
248
|
],
|
|
249
249
|
|
|
250
250
|
footer: {
|
|
251
|
-
message: `Fontist is <a href="https://
|
|
251
|
+
message: `Fontist is <a href="https://www.ribose.com/">riboseopen</a>`,
|
|
252
252
|
copyright: `Copyright © 2026 Ribose Group Inc. All rights reserved.`,
|
|
253
253
|
},
|
|
254
254
|
},
|
data/lib/fontist/cli.rb
CHANGED
|
@@ -564,7 +564,7 @@ module Fontist
|
|
|
564
564
|
styles.each do |style, installed|
|
|
565
565
|
opts = []
|
|
566
566
|
opts << "manual" if formula.manual?
|
|
567
|
-
opts << (installed
|
|
567
|
+
opts << install_label(installed)
|
|
568
568
|
msg = " #{style.type} (#{opts.join(', ')})"
|
|
569
569
|
|
|
570
570
|
if installed
|
|
@@ -578,6 +578,14 @@ module Fontist
|
|
|
578
578
|
end
|
|
579
579
|
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
|
580
580
|
|
|
581
|
+
def install_label(status)
|
|
582
|
+
case status
|
|
583
|
+
when true then "installed"
|
|
584
|
+
when false then "not installed"
|
|
585
|
+
else "installed (system)"
|
|
586
|
+
end
|
|
587
|
+
end
|
|
588
|
+
|
|
581
589
|
def print_find_results(results)
|
|
582
590
|
if results.empty?
|
|
583
591
|
Fontist.ui.say("No fonts found matching criteria")
|
data/lib/fontist/font.rb
CHANGED
|
@@ -446,8 +446,9 @@ module Fontist
|
|
|
446
446
|
def list_styles(formulas)
|
|
447
447
|
map_to_hash(formulas) do |formula|
|
|
448
448
|
map_to_hash(requested_fonts(formula.all_fonts)) do |font|
|
|
449
|
+
external = external_paths_by_type(font)
|
|
449
450
|
map_to_hash(font.styles) do |style|
|
|
450
|
-
installed(style)
|
|
451
|
+
installed(style, external)
|
|
451
452
|
end
|
|
452
453
|
end
|
|
453
454
|
end
|
|
@@ -465,8 +466,25 @@ module Fontist
|
|
|
465
466
|
end
|
|
466
467
|
end
|
|
467
468
|
|
|
468
|
-
|
|
469
|
-
|
|
469
|
+
# A font found only outside the fontist directory reports its paths
|
|
470
|
+
# instead of true, so callers can tell the copies fontist cannot
|
|
471
|
+
# update or remove from the managed ones.
|
|
472
|
+
def installed(style, external)
|
|
473
|
+
return true if path(style)
|
|
474
|
+
|
|
475
|
+
external.fetch(style.type.to_s.downcase, false)
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
# One index lookup per font name, grouped by lower-cased style type.
|
|
479
|
+
def external_paths_by_type(font)
|
|
480
|
+
entries = SystemFont.find_styles(font.name) || []
|
|
481
|
+
entries.reject { |entry| in_fontist_dir?(entry.path) }
|
|
482
|
+
.group_by { |entry| entry.type.to_s.downcase }
|
|
483
|
+
.transform_values { |group| group.map(&:path) }
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
def in_fontist_dir?(path)
|
|
487
|
+
path.start_with?(Fontist.fonts_path.to_s)
|
|
470
488
|
end
|
|
471
489
|
|
|
472
490
|
def raise_non_supported_font
|
data/lib/fontist/system_index.rb
CHANGED
|
@@ -403,8 +403,11 @@ module Fontist
|
|
|
403
403
|
end
|
|
404
404
|
|
|
405
405
|
def index_changed?
|
|
406
|
+
# Verified first: a location that holds no fonts leaves the index
|
|
407
|
+
# empty after its rebuild, and treating empty as unbuilt would rescan
|
|
408
|
+
# the disk on every lookup. Installs reach the index via add_font.
|
|
409
|
+
return false if @index_check_done # already verified in this session
|
|
406
410
|
return true if fonts.nil? || fonts.empty?
|
|
407
|
-
return false if @index_check_done # Skip if already verified in this session
|
|
408
411
|
|
|
409
412
|
# Quick check: if index was scanned recently, trust it
|
|
410
413
|
if recently_scanned?
|
data/lib/fontist/validation.rb
CHANGED
data/lib/fontist/validator.rb
CHANGED
data/lib/fontist/version.rb
CHANGED
data/packaging/nfpm.yaml
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Linux packages that wrap the tebako-packed fontist executable.
|
|
2
|
+
# Built by script/tebako/package.sh, which sets ARCH, VERSION and BINARY.
|
|
3
|
+
name: fontist
|
|
4
|
+
arch: ${ARCH}
|
|
5
|
+
platform: linux
|
|
6
|
+
version: ${VERSION}
|
|
7
|
+
section: utils
|
|
8
|
+
priority: optional
|
|
9
|
+
maintainer: Ribose Inc. <open.source@ribose.com>
|
|
10
|
+
description: |
|
|
11
|
+
Install openly-licensed fonts on Windows, Linux and Mac.
|
|
12
|
+
Self-contained build: no Ruby installation is needed.
|
|
13
|
+
vendor: Ribose Inc.
|
|
14
|
+
homepage: https://www.fontist.org
|
|
15
|
+
license: BSD-2-Clause
|
|
16
|
+
|
|
17
|
+
# fontist clones its formula repository with git, and its git gem (~> 6.0)
|
|
18
|
+
# refuses a host git older than 2.43. Debian and Ubuntu version git with
|
|
19
|
+
# epoch 1 (1:2.43.0-1), RPM distros do not, hence one dependency per packager.
|
|
20
|
+
overrides:
|
|
21
|
+
deb:
|
|
22
|
+
depends:
|
|
23
|
+
- git (>= 1:2.43)
|
|
24
|
+
rpm:
|
|
25
|
+
depends:
|
|
26
|
+
- git >= 2.43
|
|
27
|
+
|
|
28
|
+
contents:
|
|
29
|
+
- src: ${BINARY}
|
|
30
|
+
dst: /usr/bin/fontist
|
|
31
|
+
expand: true # nfpm leaves ${BINARY} in src alone without this
|
|
32
|
+
file_info:
|
|
33
|
+
mode: 0755
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Entry point of the tebako-packed fontist (copied to bin/fontist by
|
|
5
|
+
# script/tebako/stage.sh).
|
|
6
|
+
#
|
|
7
|
+
# tebako installs the locked dependencies as gems inside the package; only
|
|
8
|
+
# fontist itself sits at a path, so it goes on the load path directly.
|
|
9
|
+
# bundler/setup is not used: bundler chdirs into path gems, and the packed
|
|
10
|
+
# filesystem refuses that.
|
|
11
|
+
#
|
|
12
|
+
# Libraries loaded through FFI (yeptris, leptris, ...) are opened with the
|
|
13
|
+
# host's dlopen, which cannot see inside the package. Each one is copied
|
|
14
|
+
# once to a host cache keyed by its content, and FFI is handed that copy.
|
|
15
|
+
|
|
16
|
+
# The packed gems are the only gems this program may see. rubygems also
|
|
17
|
+
# searches the host's GEM_HOME, GEM_PATH and user gem dir (~/.gem/ruby/<abi>),
|
|
18
|
+
# so a Ruby manager such as rvm, or a `gem install --user-install`, would
|
|
19
|
+
# shadow the locked gems. Pin rubygems to the package's gem dir before
|
|
20
|
+
# anything is required.
|
|
21
|
+
packed_gem_dir = Gem.default_dir
|
|
22
|
+
ENV.delete("GEM_HOME")
|
|
23
|
+
ENV.delete("GEM_PATH")
|
|
24
|
+
Gem.use_paths(packed_gem_dir, [packed_gem_dir])
|
|
25
|
+
|
|
26
|
+
require "digest"
|
|
27
|
+
require "fileutils"
|
|
28
|
+
require "ffi"
|
|
29
|
+
|
|
30
|
+
module FontistPackedNativeLibraries
|
|
31
|
+
PACKAGE_ROOT = "/__tfs__/"
|
|
32
|
+
|
|
33
|
+
def self.cache_root
|
|
34
|
+
home = ENV["FONTIST_PATH"] || File.join(Dir.home, ".fontist")
|
|
35
|
+
File.join(home, "tebako-native")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.host_path(name)
|
|
39
|
+
return name unless name.is_a?(String) && name.start_with?(PACKAGE_ROOT)
|
|
40
|
+
return name unless File.file?(name)
|
|
41
|
+
|
|
42
|
+
bytes = File.binread(name)
|
|
43
|
+
dir = File.join(cache_root, Digest::SHA256.hexdigest(bytes)[0, 16])
|
|
44
|
+
target = File.join(dir, File.basename(name))
|
|
45
|
+
write_once(target, bytes) unless File.file?(target)
|
|
46
|
+
target
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.write_once(target, bytes)
|
|
50
|
+
FileUtils.mkdir_p(File.dirname(target))
|
|
51
|
+
partial = "#{target}.#{Process.pid}.partial"
|
|
52
|
+
File.binwrite(partial, bytes)
|
|
53
|
+
File.chmod(0o755, partial)
|
|
54
|
+
File.rename(partial, target)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# An Array argument is a list of alternatives (the first that loads wins),
|
|
58
|
+
# so the nesting is kept: only the names inside are rewritten.
|
|
59
|
+
def self.rewrite(name)
|
|
60
|
+
name.is_a?(Array) ? name.map { |n| rewrite(n) } : host_path(name)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def ffi_lib(*names)
|
|
64
|
+
super(*names.map { |name| FontistPackedNativeLibraries.rewrite(name) })
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
FFI::Library.prepend(FontistPackedNativeLibraries)
|
|
69
|
+
|
|
70
|
+
# leptris also opens libleptris from its compiled extension, which consults
|
|
71
|
+
# LEPTRIS_LIB_PATH and then package paths the host cannot open. Two copies
|
|
72
|
+
# of the library loaded side by side crash it, so both loaders are pointed
|
|
73
|
+
# at the same host copy. yeptris reads YEPTRIS_LIB_PATH the same way.
|
|
74
|
+
{
|
|
75
|
+
"leptris" => %w[LEPTRIS_LIB_PATH libleptris],
|
|
76
|
+
"yeptris" => %w[YEPTRIS_LIB_PATH libyeptris],
|
|
77
|
+
}.each do |gem_name, (variable, basename)|
|
|
78
|
+
next if ENV[variable]
|
|
79
|
+
|
|
80
|
+
spec = Gem::Specification.find_all_by_name(gem_name).max_by(&:version)
|
|
81
|
+
next unless spec
|
|
82
|
+
|
|
83
|
+
library = Dir.glob(
|
|
84
|
+
File.join(spec.full_gem_path, "**", "#{basename}.{dylib,so,dll}"),
|
|
85
|
+
).min
|
|
86
|
+
ENV[variable] = FontistPackedNativeLibraries.host_path(library) if library
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
$LOAD_PATH.unshift(File.expand_path("../vendor/fontist/lib", __dir__))
|
|
90
|
+
load File.expand_path("../vendor/fontist/exe/fontist", __dir__)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Install a fontist .deb or .rpm on a fresh distro, use it, then remove it.
|
|
3
|
+
# Runs inside a distro container (see .github/workflows/tebako-pack.yml).
|
|
4
|
+
#
|
|
5
|
+
# script/tebako/package-smoke.sh <package-dir>
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
dir="${1:?usage: package-smoke.sh <package-dir>}"
|
|
9
|
+
# apt reads a bare relative path as a package name; give it an absolute one.
|
|
10
|
+
dir="$(cd "$dir" && pwd)"
|
|
11
|
+
here="$(cd "$(dirname "$0")" && pwd)"
|
|
12
|
+
|
|
13
|
+
if command -v apt-get >/dev/null; then
|
|
14
|
+
export DEBIAN_FRONTEND=noninteractive
|
|
15
|
+
apt-get update -qq
|
|
16
|
+
apt-get install -y -qq ca-certificates "$dir"/fontist_*.deb
|
|
17
|
+
remove() { apt-get remove -y -qq fontist; }
|
|
18
|
+
else
|
|
19
|
+
dnf install -y -q "$dir"/fontist-*.rpm
|
|
20
|
+
remove() { dnf remove -y -q fontist; }
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
if command -v ruby >/dev/null; then
|
|
24
|
+
echo "package-smoke: this image has no business carrying ruby" >&2
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
"$here/smoke.sh" "$(command -v fontist)"
|
|
28
|
+
remove
|
|
29
|
+
if command -v fontist >/dev/null; then
|
|
30
|
+
echo "package-smoke: fontist still on PATH after removal" >&2
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
echo "package-smoke: ok"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Wrap a packed Linux fontist executable into .deb and .rpm packages.
|
|
3
|
+
#
|
|
4
|
+
# script/tebako/package.sh <amd64|arm64> <fontist-executable> <out-dir>
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
usage="usage: package.sh <amd64|arm64> <fontist-executable> <out-dir>"
|
|
8
|
+
arch="${1:?$usage}"
|
|
9
|
+
binary="${2:?$usage}"
|
|
10
|
+
out="${3:?$usage}"
|
|
11
|
+
|
|
12
|
+
root="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
13
|
+
version="$(sed -n 's/.*VERSION = "\(.*\)".*/\1/p' "$root/lib/fontist/version.rb")"
|
|
14
|
+
|
|
15
|
+
mkdir -p "$out"
|
|
16
|
+
BINARY="$(cd "$(dirname "$binary")" && pwd)/$(basename "$binary")"
|
|
17
|
+
export ARCH="$arch" VERSION="$version" BINARY
|
|
18
|
+
|
|
19
|
+
for packager in deb rpm; do
|
|
20
|
+
nfpm package --config "$root/packaging/nfpm.yaml" \
|
|
21
|
+
--packager "$packager" --target "$out"
|
|
22
|
+
done
|
|
23
|
+
ls -l "$out"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Press fontist into one self-contained executable with tebako v2.
|
|
3
|
+
#
|
|
4
|
+
# script/tebako/press.sh <tebako-triplet> <output-path>
|
|
5
|
+
#
|
|
6
|
+
# <tebako-triplet> is the tebako release asset suffix: linux-gnu-x86_64,
|
|
7
|
+
# linux-gnu-arm64, macos-arm64 or macos-x86_64. Needs gh, ruby and bundler.
|
|
8
|
+
# GH_TOKEN (or GITHUB_TOKEN) keeps tebako's runtime lookups clear of the
|
|
9
|
+
# anonymous GitHub API limit.
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
triplet="${1:?usage: press.sh <tebako-triplet> <output-path>}"
|
|
13
|
+
output="${2:?usage: press.sh <tebako-triplet> <output-path>}"
|
|
14
|
+
|
|
15
|
+
tebako_version="${TEBAKO_VERSION:-2.8.68}"
|
|
16
|
+
ruby_version="${PACKAGE_RUBY_VERSION:-3.3.12}"
|
|
17
|
+
here="$(cd "$(dirname "$0")" && pwd)"
|
|
18
|
+
work="$(mktemp -d)"
|
|
19
|
+
trap 'rm -rf "$work"' EXIT
|
|
20
|
+
|
|
21
|
+
export GITHUB_TOKEN="${GITHUB_TOKEN:-${GH_TOKEN:-}}"
|
|
22
|
+
|
|
23
|
+
asset="tebako-${tebako_version}-${triplet}"
|
|
24
|
+
gh release download "v${tebako_version}" --repo tamatebako/tebako \
|
|
25
|
+
--pattern "${asset}" --pattern "${asset}.sha256" --dir "$work"
|
|
26
|
+
(cd "$work" && shasum -a 256 -c "${asset}.sha256")
|
|
27
|
+
chmod +x "$work/$asset"
|
|
28
|
+
|
|
29
|
+
stage="$("$here/stage.sh" "$work/stage")"
|
|
30
|
+
|
|
31
|
+
mkdir -p "$(dirname "$output")"
|
|
32
|
+
output="$(cd "$(dirname "$output")" && pwd)/$(basename "$output")"
|
|
33
|
+
|
|
34
|
+
# tebako appends a trailer to the executable: never strip the result.
|
|
35
|
+
"$work/$asset" press --root "$stage" --entry-point bin/fontist \
|
|
36
|
+
--output "$output" --mode self-contained -R "$ruby_version"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Check that a packed (or installed) fontist works on its own.
|
|
3
|
+
#
|
|
4
|
+
# script/tebako/smoke.sh <fontist-executable>
|
|
5
|
+
#
|
|
6
|
+
# Uses a throwaway FONTIST_PATH so it never touches a real ~/.fontist.
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
fontist="${1:?usage: smoke.sh <fontist-executable>}"
|
|
10
|
+
font="${SMOKE_FONT:-Overpass}"
|
|
11
|
+
|
|
12
|
+
home="$(mktemp -d)"
|
|
13
|
+
trap 'rm -rf "$home"' EXIT
|
|
14
|
+
export FONTIST_PATH="$home"
|
|
15
|
+
|
|
16
|
+
"$fontist" version
|
|
17
|
+
"$fontist" install --accept-all-licenses "$font"
|
|
18
|
+
|
|
19
|
+
if ! find "$home/fonts" -type f | grep -q .; then
|
|
20
|
+
echo "smoke: no font file landed under $home/fonts" >&2
|
|
21
|
+
exit 1
|
|
22
|
+
fi
|
|
23
|
+
"$fontist" list "$font" | tee "$home/list.txt"
|
|
24
|
+
grep -qi "installed" "$home/list.txt"
|
|
25
|
+
echo "smoke: ok"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Build a Gemfile-rooted app around the fontist gem, the layout tebako v2
|
|
3
|
+
# presses (it refuses a root that is itself a gem source tree).
|
|
4
|
+
#
|
|
5
|
+
# script/tebako/stage.sh <stage-dir>
|
|
6
|
+
#
|
|
7
|
+
# The gem is built from this checkout, unpacked with a static gemspec (the
|
|
8
|
+
# repository gemspec lists files with `git ls-files`, which needs .git), and
|
|
9
|
+
# referenced by path, so the packed fontist is exactly this checkout's code.
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
stage="${1:?usage: stage.sh <stage-dir>}"
|
|
13
|
+
root="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
14
|
+
|
|
15
|
+
rm -rf "$stage"
|
|
16
|
+
mkdir -p "$stage/vendor" "$stage/bin"
|
|
17
|
+
stage="$(cd "$stage" && pwd)"
|
|
18
|
+
|
|
19
|
+
(cd "$root" && gem build fontist.gemspec --output "$stage/fontist.gem" >/dev/null)
|
|
20
|
+
# Unpacked directory naming differs across rubygems versions; take the one
|
|
21
|
+
# child of a fresh directory instead of guessing it.
|
|
22
|
+
unpacked="$(mktemp -d)"
|
|
23
|
+
gem unpack "$stage/fontist.gem" --target "$unpacked" >/dev/null
|
|
24
|
+
mv "$unpacked"/*/ "$stage/vendor/fontist"
|
|
25
|
+
rmdir "$unpacked"
|
|
26
|
+
gem spec "$stage/fontist.gem" --ruby > "$stage/vendor/fontist/fontist.gemspec"
|
|
27
|
+
rm "$stage/fontist.gem"
|
|
28
|
+
|
|
29
|
+
cat > "$stage/Gemfile" <<'GEMFILE'
|
|
30
|
+
source "https://rubygems.org"
|
|
31
|
+
|
|
32
|
+
gem "fontist", path: "vendor/fontist"
|
|
33
|
+
GEMFILE
|
|
34
|
+
|
|
35
|
+
cp "$root/script/tebako/entry.rb" "$stage/bin/fontist"
|
|
36
|
+
chmod +x "$stage/bin/fontist"
|
|
37
|
+
|
|
38
|
+
(cd "$stage" && bundle lock >/dev/null)
|
|
39
|
+
echo "$stage"
|
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.37
|
|
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-
|
|
11
|
+
date: 2026-11-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: down
|
|
@@ -517,9 +517,16 @@ files:
|
|
|
517
517
|
- lib/fontist/yaml/yeptris_adapter.rb
|
|
518
518
|
- lib/fontist/yaml_backend.rb
|
|
519
519
|
- lib/tasks/system_fonts.rake
|
|
520
|
+
- packaging/nfpm.yaml
|
|
520
521
|
- script/capture_system_fonts
|
|
521
522
|
- script/download_system_indexes
|
|
522
523
|
- script/generate_windows_formulas.rb
|
|
524
|
+
- script/tebako/entry.rb
|
|
525
|
+
- script/tebako/package-smoke.sh
|
|
526
|
+
- script/tebako/package.sh
|
|
527
|
+
- script/tebako/press.sh
|
|
528
|
+
- script/tebako/smoke.sh
|
|
529
|
+
- script/tebako/stage.sh
|
|
523
530
|
- script/validate_windows_fod_ci.rb
|
|
524
531
|
homepage: https://github.com/fontist/fontist
|
|
525
532
|
licenses:
|