fontist 1.8.2 → 1.8.7

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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec.yml +6 -6
  3. data/fontist.gemspec +7 -6
  4. data/lib/fontist.rb +4 -0
  5. data/lib/fontist/cli.rb +16 -24
  6. data/lib/fontist/errors.rb +51 -2
  7. data/lib/fontist/font.rb +39 -56
  8. data/lib/fontist/font_installer.rb +4 -0
  9. data/lib/fontist/font_path.rb +29 -0
  10. data/lib/fontist/formula.rb +8 -4
  11. data/lib/fontist/import/extractors.rb +4 -0
  12. data/lib/fontist/import/extractors/cpio_extractor.rb +39 -0
  13. data/lib/fontist/import/extractors/gzip_extractor.rb +27 -0
  14. data/lib/fontist/import/extractors/rpm_extractor.rb +45 -0
  15. data/lib/fontist/import/extractors/tar_extractor.rb +47 -0
  16. data/lib/fontist/import/recursive_extraction.rb +20 -6
  17. data/lib/fontist/index.rb +4 -65
  18. data/lib/fontist/indexes/base_index.rb +82 -0
  19. data/lib/fontist/indexes/filename_index.rb +19 -0
  20. data/lib/fontist/indexes/font_index.rb +21 -0
  21. data/lib/fontist/indexes/index_formula.rb +36 -0
  22. data/lib/fontist/manifest/install.rb +3 -2
  23. data/lib/fontist/manifest/locations.rb +1 -1
  24. data/lib/fontist/system_font.rb +33 -36
  25. data/lib/fontist/system_index.rb +46 -4
  26. data/lib/fontist/utils.rb +5 -0
  27. data/lib/fontist/utils/cache.rb +12 -4
  28. data/lib/fontist/utils/cpio/cpio.rb +199 -0
  29. data/lib/fontist/utils/cpio_extractor.rb +47 -0
  30. data/lib/fontist/utils/downloader.rb +7 -4
  31. data/lib/fontist/utils/gzip_extractor.rb +24 -0
  32. data/lib/fontist/utils/locking.rb +17 -0
  33. data/lib/fontist/utils/rpm_extractor.rb +44 -0
  34. data/lib/fontist/utils/tar_extractor.rb +61 -0
  35. data/lib/fontist/version.rb +1 -1
  36. metadata +37 -11
  37. data/lib/fontist/index_formula.rb +0 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1fea467133e3e6a8a287dd36a2a03790fb63859f983b0398f0f558de519a0a64
4
- data.tar.gz: b8c717aef31834b5a9b3c3f903dacf0d267ddd85aa6f0a1eca34566a45b219bf
3
+ metadata.gz: 69bc4225a7dac5b44f92364344568e4990ec3917631febbab1739a4980890308
4
+ data.tar.gz: b1bd65c7db74152b911375a6990cda7dd23f849291feeb00edd3fddda5b93f4d
5
5
  SHA512:
6
- metadata.gz: 20d44b20267db6f15f1b36be660f91690cef7c6f4b0653341231b3f18658ec0f88ea8225884b7b2ac1d06f3e8aa5be79aea600fed5be91513f43031a10b5de5b
7
- data.tar.gz: 6138e6bed40c741f21c6d116f021aef9f6c7cca24506337fe681ba5e6c6e996c8e8e6a84e50103601231d6cab9f5cafc7b5527b418d65fbd6c1477c67ceda201
6
+ metadata.gz: 298d8927f07494407568e35fea9a3ed6fc26a725df7dcd9f4a6f3e134be628bc38bc315b0d61bac63c15c92501396b04c8e59dcad59429420785fdeaf9d4ac22
7
+ data.tar.gz: 27f7bf0e155c8c3210030de3e5d1f140b4b0cee26214ca48c5cf34136eb09f8850f80178aa331b608c61583af003c8d7ca4ac071601e3fe8dbbebd25e6e15e9d
@@ -13,17 +13,17 @@ jobs:
13
13
  strategy:
14
14
  fail-fast: false
15
15
  matrix:
16
- ruby: [ '2.6', '2.5', '2.4' ]
16
+ ruby: [ '2.4', '2.5', '2.6', '2.7' ]
17
17
  os: [ ubuntu-latest, windows-latest, macos-latest ]
18
18
  experimental: [ false ]
19
19
  include:
20
- - ruby: '2.7'
20
+ - ruby: '3.0'
21
21
  os: 'ubuntu-latest'
22
22
  experimental: true
23
- - ruby: '2.7'
23
+ - ruby: '3.0'
24
24
  os: 'windows-latest'
25
25
  experimental: true
26
- - ruby: '2.7'
26
+ - ruby: '3.0'
27
27
  os: 'macos-latest'
28
28
  experimental: true
29
29
 
@@ -37,8 +37,8 @@ jobs:
37
37
  - uses: actions/cache@v1
38
38
  with:
39
39
  path: vendor/bundle
40
- key: bundle-${{ matrix.os }}-${{ matrix.ruby }}-${{ hashFiles('**/*.gemspec') }}
41
- restore-keys: bundle-${{ matrix.os }}-${{ matrix.ruby }}
40
+ key: bundle-v2-${{ matrix.os }}-${{ matrix.ruby }}-${{ hashFiles('**/*.gemspec') }}
41
+ restore-keys: bundle-v2-${{ matrix.os }}-${{ matrix.ruby }}
42
42
 
43
43
  - if: matrix.os == 'macos-latest'
44
44
  run: brew install lcdf-typetools
data/fontist.gemspec CHANGED
@@ -5,15 +5,15 @@ require "fontist/version"
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "fontist"
7
7
  spec.version = Fontist::VERSION
8
- spec.authors = ["Ribose Inc.", "Abu Nashir"]
9
- spec.email = ["operations@ribose.com", "abunashir@gmail.com"]
8
+ spec.authors = ["Ribose Inc."]
9
+ spec.email = ["open.source@ribose.com"]
10
10
 
11
- spec.summary = %q{A libarary find or download fonts}
12
- spec.description = %q{A libarary find or download fonts}
11
+ spec.summary = %q{Install openly-licensed fonts on Windows, Linux and Mac!}
12
+ spec.description = %q{Install openly-licensed fonts on Windows, Linux and Mac!}
13
13
  spec.homepage = "https://github.com/fontist/fontist"
14
14
  spec.license = "BSD-2-Clause"
15
15
 
16
- spec.post_install_message = "Please run `fontist update` to fetch formulas"
16
+ spec.post_install_message = "Please run `fontist update` to fetch formulas."
17
17
 
18
18
  spec.metadata["homepage_uri"] = spec.homepage
19
19
  spec.metadata["source_code_uri"] = "https://github.com/fontist/fontist"
@@ -27,6 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.executables = ["fontist"]
28
28
  spec.test_files = `git ls-files -- {spec}/*`.split("\n")
29
29
 
30
+ spec.add_runtime_dependency "arr-pm", "~> 0.0.1"
30
31
  spec.add_runtime_dependency "down", "~> 5.0"
31
32
  spec.add_runtime_dependency "libmspack", "~> 0.1.0"
32
33
  spec.add_runtime_dependency "rubyzip", "~> 2.3.0"
@@ -41,7 +42,7 @@ Gem::Specification.new do |spec|
41
42
  spec.add_development_dependency "bundler", "~> 2.0"
42
43
  spec.add_development_dependency "gem-release"
43
44
  spec.add_development_dependency "nokogiri", "~> 1.0"
44
- spec.add_development_dependency "rake", "~> 12.3.3"
45
+ spec.add_development_dependency "rake", "~> 13"
45
46
  spec.add_development_dependency "rspec", "~> 3.0"
46
47
  spec.add_development_dependency "rubocop", "0.75.0"
47
48
  spec.add_development_dependency "rubocop-rails"
data/lib/fontist.rb CHANGED
@@ -62,4 +62,8 @@ module Fontist
62
62
  def self.formula_index_path
63
63
  Fontist.formulas_repo_path.join("index.yml")
64
64
  end
65
+
66
+ def self.formula_filename_index_path
67
+ Fontist.formulas_repo_path.join("filename_index.yml")
68
+ end
65
69
  end
data/lib/fontist/cli.rb CHANGED
@@ -9,15 +9,17 @@ module Fontist
9
9
  STATUS_LICENSING_ERROR = 4
10
10
  STATUS_MANIFEST_COULD_NOT_BE_FOUND_ERROR = 5
11
11
  STATUS_MANIFEST_COULD_NOT_BE_READ_ERROR = 6
12
+ STATUS_FONT_INDEX_CORRUPTED = 7
12
13
 
13
14
  ERROR_TO_STATUS = {
14
- Fontist::Errors::NonSupportedFontError => [STATUS_NON_SUPPORTED_FONT_ERROR],
15
+ Fontist::Errors::UnsupportedFontError => [STATUS_NON_SUPPORTED_FONT_ERROR],
15
16
  Fontist::Errors::MissingFontError => [STATUS_MISSING_FONT_ERROR],
16
17
  Fontist::Errors::LicensingError => [STATUS_LICENSING_ERROR],
17
18
  Fontist::Errors::ManifestCouldNotBeFoundError => [STATUS_MANIFEST_COULD_NOT_BE_FOUND_ERROR,
18
19
  "Manifest could not be found."],
19
20
  Fontist::Errors::ManifestCouldNotBeReadError => [STATUS_MANIFEST_COULD_NOT_BE_READ_ERROR,
20
21
  "Manifest could not be read."],
22
+ Fontist::Errors::FontIndexCorrupted => [STATUS_FONT_INDEX_CORRUPTED],
21
23
  }.freeze
22
24
 
23
25
  def self.exit_on_failure?
@@ -27,12 +29,14 @@ module Fontist
27
29
  desc "install FONT", "Install font"
28
30
  option :force, type: :boolean, aliases: :f,
29
31
  desc: "Install even if it's already installed in system"
30
- option :confirm_license, type: :boolean, desc: "Confirm license agreement"
32
+ option :accept_all_licenses, type: :boolean, aliases: "--confirm-license", desc: "Accept all license agreements"
33
+ option :hide_licenses, type: :boolean, desc: "Hide license texts"
31
34
  def install(font)
32
35
  Fontist::Font.install(
33
36
  font,
34
37
  force: options[:force],
35
- confirmation: options[:confirm_license] ? "yes" : "no"
38
+ confirmation: options[:accept_all_licenses] ? "yes" : "no",
39
+ hide_licenses: options[:hide_licenses]
36
40
  )
37
41
  success
38
42
  rescue Fontist::Errors::GeneralError => e
@@ -50,12 +54,11 @@ module Fontist
50
54
  end
51
55
  map remove: :uninstall
52
56
 
53
- desc "status [FONT]", "Show status of FONT or all fonts in fontist"
57
+ desc "status [FONT]", "Show paths of FONT or all fonts"
54
58
  def status(font = nil)
55
- formulas = Fontist::Font.status(font)
56
- return error("No font is installed.", STATUS_MISSING_FONT_ERROR) if formulas.empty?
59
+ paths = Fontist::Font.status(font)
60
+ return error("No font is installed.", STATUS_MISSING_FONT_ERROR) if paths.empty?
57
61
 
58
- print_formulas(formulas)
59
62
  success
60
63
  rescue Fontist::Errors::GeneralError => e
61
64
  handle_error(e)
@@ -88,11 +91,13 @@ module Fontist
88
91
  end
89
92
 
90
93
  desc "manifest-install MANIFEST", "Install fonts from MANIFEST (yaml)"
91
- option :confirm_license, type: :boolean, desc: "Confirm license agreement"
94
+ option :accept_all_licenses, type: :boolean, aliases: "--confirm-license", desc: "Accept all license agreements"
95
+ option :hide_licenses, type: :boolean, desc: "Hide license texts"
92
96
  def manifest_install(manifest)
93
97
  paths = Fontist::Manifest::Install.from_file(
94
98
  manifest,
95
- confirmation: options[:confirm_license] ? "yes" : "no"
99
+ confirmation: options[:accept_all_licenses] ? "yes" : "no",
100
+ hide_licenses: options[:hide_licenses]
96
101
  )
97
102
 
98
103
  print_yaml(paths)
@@ -105,7 +110,8 @@ module Fontist
105
110
  option :name, desc: "Example: Times New Roman"
106
111
  option :mirror, repeatable: true
107
112
  option :subarchive, desc: "Subarchive to choose when there are several ones"
108
- option :subdir, desc: "Subdirectory to take fonts from"
113
+ option :subdir, desc: "Subdirectory to take fonts from, starting with the " \
114
+ "root dir, e.g.: stixfonts-2.10/fonts/static_otf. May include `fnmatch` patterns."
109
115
  def create_formula(url)
110
116
  require "fontist/import/create_formula"
111
117
  name = Fontist::Import::CreateFormula.new(url, options).call
@@ -152,20 +158,6 @@ module Fontist
152
158
  Fontist.ui.say(YAML.dump(object))
153
159
  end
154
160
 
155
- def print_formulas(formulas)
156
- formulas.each do |formula, fonts|
157
- Fontist.ui.success(formula.key)
158
-
159
- fonts.each do |font, styles|
160
- Fontist.ui.success(" #{font.name}")
161
-
162
- styles.each do |style, path|
163
- Fontist.ui.success(" #{style.type} (#{path})")
164
- end
165
- end
166
- end
167
- end
168
-
169
161
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
170
162
  def print_list(formulas)
171
163
  formulas.each do |formula, fonts|
@@ -1,7 +1,9 @@
1
1
  module Fontist
2
2
  module Errors
3
3
  class GeneralError < StandardError; end
4
+
4
5
  class BinaryCallError < GeneralError; end
6
+ class FontIndexCorrupted < GeneralError; end
5
7
  class FontNotFoundError < GeneralError; end
6
8
  class FormulaIndexNotFoundError < GeneralError; end
7
9
  class InvalidResourceError < GeneralError; end
@@ -9,10 +11,57 @@ module Fontist
9
11
  class ManifestCouldNotBeFoundError < GeneralError; end
10
12
  class ManifestCouldNotBeReadError < GeneralError; end
11
13
  class MissingAttributeError < GeneralError; end
12
- class MissingFontError < GeneralError; end
13
- class NonSupportedFontError < GeneralError; end
14
14
  class TamperedFileError < GeneralError; end
15
15
  class TimeoutError < GeneralError; end
16
16
  class UnknownFontTypeError < GeneralError; end
17
+ class UnknownArchiveError < GeneralError; end
18
+
19
+ class FontError < GeneralError
20
+ attr_reader :font, :style
21
+
22
+ def initialize(msg, font = nil, style = nil)
23
+ @font = font
24
+ @style = style
25
+
26
+ super(msg)
27
+ end
28
+
29
+ def name
30
+ messages = []
31
+ messages << "Font name: '#{@font}'"
32
+ messages << "Style: '#{@style}'" if @style
33
+ messages.join("; ")
34
+ end
35
+ end
36
+
37
+ class MissingFontError < FontError
38
+ def initialize(font, style = nil)
39
+ name = prepare_name(font, style)
40
+ msg = "#{name} font is missing, please run `fontist install '#{font}'` to download the font."
41
+
42
+ super(msg, font, style)
43
+ end
44
+
45
+ private
46
+
47
+ def prepare_name(font, style)
48
+ names = []
49
+ names << "'#{font}'"
50
+ names << "'#{style}'" if style
51
+ names.join(" ")
52
+ end
53
+ end
54
+
55
+ class UnsupportedFontError < FontError
56
+ def initialize(font)
57
+ msg = <<~MSG.chomp
58
+ Font '#{font}' not found locally nor available in the Fontist formula repository.
59
+ Perhaps it is available at the latest Fontist formula repository.
60
+ You can update the formula repository using the command `fontist update` and try again.
61
+ MSG
62
+
63
+ super(msg, font)
64
+ end
65
+ end
17
66
  end
18
67
  end
data/lib/fontist/font.rb CHANGED
@@ -1,10 +1,12 @@
1
1
  require "fontist/font_installer"
2
+ require "fontist/font_path"
2
3
 
3
4
  module Fontist
4
5
  class Font
5
6
  def initialize(options = {})
6
7
  @name = options[:name]
7
8
  @confirmation = options[:confirmation] || "no"
9
+ @hide_licenses = options[:hide_licenses]
8
10
  @force = options[:force] || false
9
11
 
10
12
  check_or_create_fontist_path!
@@ -18,8 +20,8 @@ module Fontist
18
20
  new(name: name).find
19
21
  end
20
22
 
21
- def self.install(name, confirmation: "no", force: false)
22
- new(name: name, confirmation: confirmation, force: force).install
23
+ def self.install(name, options = {})
24
+ new(options.merge(name: name)).install
23
25
  end
24
26
 
25
27
  def self.uninstall(name)
@@ -47,9 +49,9 @@ module Fontist
47
49
  end
48
50
 
49
51
  def status
50
- return installed_statuses unless @name
52
+ return installed_paths unless @name
51
53
 
52
- font_status || downloadable_font || raise_non_supported_font
54
+ find_system_font || downloadable_font || raise_non_supported_font
53
55
  end
54
56
 
55
57
  def list
@@ -64,7 +66,7 @@ module Fontist
64
66
 
65
67
  private
66
68
 
67
- attr_reader :name, :confirmation
69
+ attr_reader :name
68
70
 
69
71
  def find_system_font
70
72
  paths = Fontist::SystemFont.find(name)
@@ -73,9 +75,14 @@ module Fontist
73
75
  return
74
76
  end
75
77
 
78
+ print_paths(paths)
79
+ end
80
+
81
+ def print_paths(paths)
76
82
  Fontist.ui.say("Fonts found at:")
77
83
  paths.each do |path|
78
- Fontist.ui.say("- #{path}")
84
+ font_path = FontPath.new(path)
85
+ Fontist.ui.say(font_path.to_s)
79
86
  end
80
87
  end
81
88
 
@@ -94,20 +101,21 @@ module Fontist
94
101
  @formula ||= Fontist::Formula.find(name)
95
102
  end
96
103
 
104
+ def formulas
105
+ @formulas ||= Fontist::Formula.find_many(name)
106
+ end
107
+
97
108
  def downloadable_font
98
109
  if formula
99
- raise(
100
- Fontist::Errors::MissingFontError,
101
- "#{name} fonts are missing, please run " \
102
- "`fontist install '#{name}'` to " \
103
- "download the font."
104
- )
110
+ raise Fontist::Errors::MissingFontError.new(name)
105
111
  end
106
112
  end
107
113
 
108
114
  def download_font
109
- if formula
110
- check_and_confirm_required_license(formula)
115
+ return if formulas.empty?
116
+
117
+ formulas.flat_map do |formula|
118
+ confirmation = check_and_confirm_required_license(formula)
111
119
  paths = font_installer(formula).install(confirmation: confirmation)
112
120
 
113
121
  Fontist.ui.say("Fonts installed at:")
@@ -118,19 +126,24 @@ module Fontist
118
126
  end
119
127
 
120
128
  def check_and_confirm_required_license(formula)
121
- if formula.license_required && !confirmation.casecmp("yes").zero?
122
- @confirmation = show_license_and_ask_for_input(formula.license)
129
+ return @confirmation unless formula.license_required
123
130
 
124
- unless confirmation&.casecmp?("yes")
125
- raise Fontist::Errors::LicensingError.new(
126
- "Fontist will not download these fonts unless you accept the terms."
127
- )
128
- end
129
- end
131
+ show_license(formula.license) unless @hide_licenses
132
+ return @confirmation if @confirmation.casecmp?("yes")
133
+
134
+ confirmation = ask_for_agreement
135
+ return confirmation if confirmation&.casecmp?("yes")
136
+
137
+ raise Fontist::Errors::LicensingError.new(
138
+ "Fontist will not download these fonts unless you accept the terms."
139
+ )
130
140
  end
131
141
 
132
- def show_license_and_ask_for_input(license)
142
+ def show_license(license)
133
143
  Fontist.ui.say(license_agrement_message(license))
144
+ end
145
+
146
+ def ask_for_agreement
134
147
  Fontist.ui.ask(
135
148
  "\nDo you accept all presented font licenses, and want Fontist " \
136
149
  "to download these fonts for you? => TYPE 'Yes' or 'No':"
@@ -166,37 +179,14 @@ module Fontist
166
179
  Fontist::FontistFont.find(name)
167
180
  end
168
181
 
169
- def installed_statuses
170
- installed_styles(all_formulas)
182
+ def installed_paths
183
+ print_paths(SystemFont.font_paths)
171
184
  end
172
185
 
173
186
  def all_formulas
174
187
  Fontist::Formula.all
175
188
  end
176
189
 
177
- def font_status
178
- return unless formula
179
-
180
- statuses = installed_styles([formula])
181
- statuses.empty? ? nil : statuses
182
- end
183
-
184
- def installed_styles(formulas)
185
- filter_blank(formulas) do |formula|
186
- filter_blank(formula.fonts) do |font|
187
- filter_blank(font.styles) do |style|
188
- path(style)
189
- end
190
- end
191
- end
192
- end
193
-
194
- def filter_blank(elements)
195
- elements.map { |e| [e, yield(e)] }
196
- .to_h
197
- .reject { |_k, v| v.nil? || v.empty? }
198
- end
199
-
200
190
  def path(style)
201
191
  font_paths.detect do |path|
202
192
  File.basename(path) == style.font
@@ -236,14 +226,7 @@ module Fontist
236
226
  end
237
227
 
238
228
  def raise_non_supported_font
239
- raise Fontist::Errors::NonSupportedFontError.new(
240
- "Font '#{@name}' not found locally nor available in the Fontist " \
241
- "formula repository.\n" \
242
- "Perhaps it is available at the latest Fontist formula " \
243
- "repository.\n" \
244
- "You can update the formula repository using the command " \
245
- "`fontist update` and try again."
246
- )
229
+ raise Fontist::Errors::UnsupportedFontError.new(@name)
247
230
  end
248
231
  end
249
232
  end
@@ -6,6 +6,10 @@ module Fontist
6
6
  include Utils::ExeExtractor
7
7
  include Utils::MsiExtractor
8
8
  include Utils::SevenZipExtractor
9
+ include Utils::RpmExtractor
10
+ include Utils::GzipExtractor
11
+ include Utils::CpioExtractor
12
+ include Utils::TarExtractor
9
13
 
10
14
  def initialize(formula)
11
15
  @formula = formula