fontist 1.8.2 → 1.8.7

Sign up to get free protection for your applications and to get access to all the features.
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