fontist 1.8.13 → 1.10.1

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.
data/README.md CHANGED
@@ -399,6 +399,70 @@ bin/rspec
399
399
  All formulas are kept in the [formulas][fontist-formulas] repository. If you'd
400
400
  like to add a new one or change any existing, please refer to its documentation.
401
401
 
402
+ ### Private repos
403
+
404
+ There is an ability to use private fonts via private fontist repo. Fontist repo
405
+ is a git repo which contains YAML formula files. Formulas can be created
406
+ manually (see [examples](https://github.com/fontist/formulas/tree/master/Formulas)),
407
+ or [auto-generated from an archive](#auto-generate-a-formula).
408
+
409
+ A repo can be either HTTPS or SSH Git repo. In case of SSH, a corresponding SSH key
410
+ should be setup with ssh-agent in order to access this private repo.
411
+
412
+ The `repo setup` command fetches a repo's formulas, and saves repo's name and url
413
+ for later use.
414
+
415
+ Internally all repos are stored at `~/.fontist/formulas/Formulas/private`.
416
+
417
+ ```sh
418
+ fontist repo setup NAME URL
419
+ ```
420
+
421
+ E.g.
422
+
423
+ ```sh
424
+ fontist repo setup acme https://example.com/acme/formulas.git
425
+ # or
426
+ fontist repo setup acme git@example.com:acme/formulas.git
427
+ ```
428
+
429
+ Then you can just install fonts from this repo:
430
+
431
+ ```sh
432
+ fontist install "private font"
433
+ ```
434
+
435
+ There is no need in any additional command to be run, but if you add new
436
+ formulas to your repo, you can fetch them with the `repo update` command:
437
+
438
+ ```sh
439
+ fontist repo update acme
440
+ ```
441
+
442
+ If there is a need to avoid using private formulas, the repo can be removed with:
443
+
444
+ ```sh
445
+ fontist repo remove acme
446
+ ```
447
+
448
+ ### Private formulas
449
+
450
+ Authorization of private archives in private formulas can be implemented with
451
+ headers. Here is an example which works with Github releases:
452
+
453
+ ```yaml
454
+ resources:
455
+ fonts.zip:
456
+ urls:
457
+ - url: https://example.com/repos/acme/formulas/releases/assets/38777461
458
+ headers:
459
+ Accept: application/octet-stream
460
+ Authorization: token ghp_1234567890abcdefghi
461
+ ```
462
+
463
+ A token can be obtained on [this page](https://github.com/settings/tokens).
464
+ It should have at least the `repo` scope.
465
+
402
466
  ### Auto-generate a formula
403
467
 
404
468
  A formula could be generated from a fonts archive. Just specify a URL to the
@@ -409,20 +473,21 @@ fontist create-formula https://www.latofonts.com/download/lato2ofl-zip/
409
473
  cp lato.yml ~/.fontist/formulas/Formulas/
410
474
  ```
411
475
 
476
+ Though indexes are auto-generated now, maintainers should rebuild indexes
477
+ in the main repo for backward compatibility with fontist prior to 1.9.x versions.
412
478
  A formula index should be rebuild, when a new formula is generated or an
413
479
  existing one changed:
414
480
 
415
481
  ```sh
416
- fontist rebuild-index
482
+ fontist rebuild-index --main-repo
417
483
  ```
418
484
 
419
- Then, both the formula and the updated index should be commited and pushed to
485
+ Then, both the formula and the updated indexes should be commited and pushed to
420
486
  the formula repository:
421
487
 
422
488
  ```sh
423
489
  cd ~/.fontist/formulas
424
- git add Formulas/lato.yml
425
- git add index.yml
490
+ git add Formulas/lato.yml index.yml filename_index.yml
426
491
  git commit -m "Add Lato formula"
427
492
  ```
428
493
 
@@ -441,7 +506,7 @@ repository [formulas][fontist-formulas]:
441
506
 
442
507
  ```
443
508
  cd ~/.fontist/formulas
444
- git add Formulas/google
509
+ git add Formulas/google index.yml filename_index.yml
445
510
  git commit -m "Google Fonts update"
446
511
  git push
447
512
  ```
@@ -454,12 +519,23 @@ can be updated with:
454
519
  ```sh
455
520
  fontist import-sil
456
521
  cd ~/.fontist/formulas
457
- git add Formulas/sil
458
- git add index.yml
522
+ git add Formulas/sil index.yml filename_index.yml
459
523
  git commit -m "SIL fonts update"
460
524
  git push
461
525
  ```
462
526
 
527
+ ### Using with proxy
528
+
529
+ `fontist` can read proxy settings from environemnt variables:
530
+
531
+ * `HTTP_PROXY`
532
+ * `SOCKS_PROXY`
533
+
534
+ Also because `fontist` uses git under the hood, proxy must be configured in `~/.gitconfig` separately.
535
+ Check [nice guide](https://gist.github.com/evantoli/f8c23a37eb3558ab8765) about how it can be configured for more details
536
+
537
+ Also as for regular URL you can pass username and password, like `http://username:password@example.com/` for SOCKS it's similar
538
+
463
539
  ### Releasing
464
540
 
465
541
  Releasing is done automatically with GitHub Action. Just bump and tag with `gem-release`.
data/exe/fontist CHANGED
@@ -3,5 +3,27 @@
3
3
  require "fontist"
4
4
  require "fontist/cli"
5
5
 
6
- status_code = Fontist::CLI.start(ARGV)
7
- exit status_code.is_a?(Integer) ? status_code : 1
6
+ fontist_cli = proc {
7
+ status_code = Fontist::CLI.start(ARGV)
8
+ exit status_code.is_a?(Integer) ? status_code : 1
9
+ }
10
+
11
+ if ENV["SOCKS_PROXY"]
12
+ require "socksify"
13
+ require "uri"
14
+ begin
15
+ proxy = URI.parse(ENV["SOCKS_PROXY"])
16
+ if proxy.userinfo
17
+ user, pass = proxy.userinfo.split(":")
18
+ TCPSocket::socks_username = user
19
+ TCPSocket::socks_password = pass
20
+ end
21
+ Socksify::proxy(proxy.host, proxy.port, &fontist_cli)
22
+ rescue URI::InvalidURIError
23
+ warn "Value of ENV.SOCKS_PROXY=#{ENV['SOCKS_PROXY']} is invalid! Droping it"
24
+ ENV.delete("SOCKS_PROXY")
25
+ fontist_cli.call
26
+ end
27
+ else
28
+ fontist_cli.call
29
+ end
data/fontist.gemspec CHANGED
@@ -40,8 +40,10 @@ Gem::Specification.new do |spec|
40
40
  spec.add_development_dependency "nokogiri", "~> 1.0"
41
41
  spec.add_development_dependency "rake", "~> 13"
42
42
  spec.add_development_dependency "rspec", "~> 3.0"
43
- spec.add_development_dependency "rubocop", "0.75.0"
43
+ spec.add_development_dependency "rubocop", "1.5.2"
44
44
  spec.add_development_dependency "rubocop-rails"
45
45
  spec.add_development_dependency "rubocop-performance"
46
46
  spec.add_development_dependency "ruby-protocol-buffers", "~> 1.0"
47
+
48
+ spec.add_runtime_dependency "socksify"
47
49
  end
data/lib/fontist.rb CHANGED
@@ -7,10 +7,10 @@ require "singleton"
7
7
  require "fontist/errors"
8
8
  require "fontist/version"
9
9
 
10
+ require "fontist/repo"
10
11
  require "fontist/font"
11
12
  require "fontist/formula"
12
13
  require "fontist/system_font"
13
- require "fontist/fontist_font"
14
14
  require "fontist/manifest"
15
15
  require "fontist/helpers"
16
16
 
@@ -28,7 +28,11 @@ module Fontist
28
28
  end
29
29
 
30
30
  def self.fontist_path
31
- Pathname.new(ENV["FONTIST_PATH"] || File.join(Dir.home, ".fontist"))
31
+ Pathname.new(ENV["FONTIST_PATH"] || default_fontist_path)
32
+ end
33
+
34
+ def self.default_fontist_path
35
+ Pathname.new(File.join(Dir.home, ".fontist"))
32
36
  end
33
37
 
34
38
  def self.fonts_path
@@ -47,6 +51,10 @@ module Fontist
47
51
  Fontist.formulas_repo_path.join("Formulas")
48
52
  end
49
53
 
54
+ def self.private_formulas_path
55
+ Fontist.formulas_path.join("private")
56
+ end
57
+
50
58
  def self.downloads_path
51
59
  Fontist.fontist_path.join("downloads")
52
60
  end
@@ -56,14 +64,52 @@ module Fontist
56
64
  end
57
65
 
58
66
  def self.system_index_path
59
- Fontist.fontist_path.join("system_index.yml")
67
+ Fontist.fontist_path.join("system_index.default_family.yml")
68
+ end
69
+
70
+ def self.system_preferred_family_index_path
71
+ Fontist.fontist_path.join("system_index.preferred_family.yml")
72
+ end
73
+
74
+ def self.fontist_index_path
75
+ Fontist.fontist_path.join("fontist_index.default_family.yml")
76
+ end
77
+
78
+ def self.fontist_preferred_family_index_path
79
+ Fontist.fontist_path.join("fontist_index.preferred_family.yml")
60
80
  end
61
81
 
62
82
  def self.formula_index_path
63
- Fontist.formulas_repo_path.join("index.yml")
83
+ Fontist.formula_index_dir.join("formula_index.default_family.yml")
84
+ end
85
+
86
+ def self.formula_preferred_family_index_path
87
+ @formula_preferred_family_index_path ||
88
+ Fontist.formula_index_dir.join("formula_index.preferred_family.yml")
89
+ end
90
+
91
+ def self.formula_preferred_family_index_path=(path)
92
+ @formula_preferred_family_index_path = path
64
93
  end
65
94
 
66
95
  def self.formula_filename_index_path
67
- Fontist.formulas_repo_path.join("filename_index.yml")
96
+ @formula_filename_index_path ||
97
+ Fontist.formula_index_dir.join("filename_index.yml")
98
+ end
99
+
100
+ def self.formula_filename_index_path=(path)
101
+ @formula_filename_index_path = path
102
+ end
103
+
104
+ def self.formula_index_dir
105
+ Fontist.fontist_path
106
+ end
107
+
108
+ def self.preferred_family?
109
+ !!@preferred_family
110
+ end
111
+
112
+ def self.preferred_family=(bool)
113
+ @preferred_family = bool
68
114
  end
69
115
  end
data/lib/fontist/cli.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "thor"
2
+ require "fontist/repo_cli"
2
3
 
3
4
  module Fontist
4
5
  class CLI < Thor
@@ -10,6 +11,9 @@ module Fontist
10
11
  STATUS_MANIFEST_COULD_NOT_BE_FOUND_ERROR = 5
11
12
  STATUS_MANIFEST_COULD_NOT_BE_READ_ERROR = 6
12
13
  STATUS_FONT_INDEX_CORRUPTED = 7
14
+ STATUS_REPO_NOT_FOUND = 8
15
+ STATUS_MAIN_REPO_NOT_FOUND = 9
16
+ STATUS_REPO_COULD_NOT_BE_UPDATED = 10
13
17
 
14
18
  ERROR_TO_STATUS = {
15
19
  Fontist::Errors::UnsupportedFontError => [STATUS_NON_SUPPORTED_FONT_ERROR],
@@ -20,12 +24,18 @@ module Fontist
20
24
  Fontist::Errors::ManifestCouldNotBeReadError => [STATUS_MANIFEST_COULD_NOT_BE_READ_ERROR,
21
25
  "Manifest could not be read."],
22
26
  Fontist::Errors::FontIndexCorrupted => [STATUS_FONT_INDEX_CORRUPTED],
27
+ Fontist::Errors::RepoNotFoundError => [STATUS_REPO_NOT_FOUND],
28
+ Fontist::Errors::MainRepoNotFoundError => [STATUS_MAIN_REPO_NOT_FOUND],
23
29
  }.freeze
24
30
 
25
31
  def self.exit_on_failure?
26
32
  false
27
33
  end
28
34
 
35
+ class_option :preferred_family,
36
+ type: :boolean,
37
+ desc: "Use Preferred Family when available"
38
+
29
39
  desc "install FONT", "Install font"
30
40
  option :force, type: :boolean, aliases: :f,
31
41
  desc: "Install even if it's already installed in system"
@@ -33,6 +43,7 @@ module Fontist
33
43
  option :hide_licenses, type: :boolean, desc: "Hide license texts"
34
44
  option :no_progress, type: :boolean, desc: "Hide download progress"
35
45
  def install(font)
46
+ handle_class_options(options)
36
47
  Fontist::Font.install(
37
48
  font,
38
49
  force: options[:force],
@@ -47,6 +58,7 @@ module Fontist
47
58
 
48
59
  desc "uninstall/remove FONT", "Uninstall font by font or formula"
49
60
  def uninstall(font)
61
+ handle_class_options(options)
50
62
  fonts_paths = Fontist::Font.uninstall(font)
51
63
  Fontist.ui.success("These fonts are removed:")
52
64
  Fontist.ui.success(fonts_paths.join("\n"))
@@ -58,6 +70,7 @@ module Fontist
58
70
 
59
71
  desc "status [FONT]", "Show paths of FONT or all fonts"
60
72
  def status(font = nil)
73
+ handle_class_options(options)
61
74
  paths = Fontist::Font.status(font)
62
75
  return error("No font is installed.", STATUS_MISSING_FONT_ERROR) if paths.empty?
63
76
 
@@ -68,6 +81,7 @@ module Fontist
68
81
 
69
82
  desc "list [FONT]", "List installation status of FONT or fonts in fontist"
70
83
  def list(font = nil)
84
+ handle_class_options(options)
71
85
  formulas = Fontist::Font.list(font)
72
86
  print_list(formulas)
73
87
  success
@@ -77,14 +91,19 @@ module Fontist
77
91
 
78
92
  desc "update", "Update formulas"
79
93
  def update
94
+ handle_class_options(options)
80
95
  Formula.update_formulas_repo
81
- Fontist.ui.say("Formulas have been successfully updated")
96
+ Fontist.ui.success("Formulas have been successfully updated.")
82
97
  success
98
+ rescue Fontist::Errors::RepoCouldNotBeUpdatedError => e
99
+ Fontist.ui.error(e.message)
100
+ STATUS_REPO_COULD_NOT_BE_UPDATED
83
101
  end
84
102
 
85
103
  desc "manifest-locations MANIFEST",
86
104
  "Get locations of fonts from MANIFEST (yaml)"
87
105
  def manifest_locations(manifest)
106
+ handle_class_options(options)
88
107
  paths = Fontist::Manifest::Locations.from_file(manifest)
89
108
  print_yaml(paths)
90
109
  success
@@ -96,6 +115,7 @@ module Fontist
96
115
  option :accept_all_licenses, type: :boolean, aliases: "--confirm-license", desc: "Accept all license agreements"
97
116
  option :hide_licenses, type: :boolean, desc: "Hide license texts"
98
117
  def manifest_install(manifest)
118
+ handle_class_options(options)
99
119
  paths = Fontist::Manifest::Install.from_file(
100
120
  manifest,
101
121
  confirmation: options[:accept_all_licenses] ? "yes" : "no",
@@ -115,6 +135,7 @@ module Fontist
115
135
  option :subdir, desc: "Subdirectory to take fonts from, starting with the " \
116
136
  "root dir, e.g.: stixfonts-2.10/fonts/static_otf. May include `fnmatch` patterns."
117
137
  def create_formula(url)
138
+ handle_class_options(options)
118
139
  require "fontist/import/create_formula"
119
140
  name = Fontist::Import::CreateFormula.new(url, options).call
120
141
  Fontist.ui.say("#{name} formula has been successfully created")
@@ -123,23 +144,43 @@ module Fontist
123
144
 
124
145
  desc "rebuild-index", "Rebuild formula index (used by formulas maintainers)"
125
146
  long_desc <<-LONGDESC
126
- This index is pre-built and served with formulas, so there is no need
127
- update it unless something changes in the formulas repo.
147
+ Index should be rebuilt when any formula changes.
148
+
149
+ It is done automatically when formulas are updated, or private formulas
150
+ are set up.
128
151
  LONGDESC
152
+ option :main_repo, type: :boolean,
153
+ desc: "Updates indexes in the main repo (for backward " \
154
+ "compatibility with versions prior to 1.9)"
129
155
  def rebuild_index
130
- Fontist::Index.rebuild
156
+ handle_class_options(options)
157
+
158
+ if options[:main_repo]
159
+ Fontist::Index.rebuild_for_main_repo
160
+ else
161
+ Fontist::Index.rebuild
162
+ end
163
+
131
164
  Fontist.ui.say("Formula index has been rebuilt.")
132
165
  STATUS_SUCCESS
133
166
  end
134
167
 
135
168
  desc "import-sil", "Import formulas from SIL"
136
169
  def import_sil
170
+ handle_class_options(options)
137
171
  require "fontist/import/sil_import"
138
172
  Fontist::Import::SilImport.new.call
139
173
  end
140
174
 
175
+ desc "repo SUBCOMMAND ...ARGS", "Manage custom repositories"
176
+ subcommand "repo", Fontist::RepoCLI
177
+
141
178
  private
142
179
 
180
+ def handle_class_options(options)
181
+ Fontist.preferred_family = options[:preferred_family]
182
+ end
183
+
143
184
  def success
144
185
  STATUS_SUCCESS
145
186
  end
@@ -3,17 +3,37 @@ module Fontist
3
3
  class GeneralError < StandardError; end
4
4
 
5
5
  class BinaryCallError < GeneralError; end
6
+
6
7
  class FontIndexCorrupted < GeneralError; end
8
+
7
9
  class FontNotFoundError < GeneralError; end
10
+
11
+ # for backward compatibility with metanorma,
12
+ # it depends on this exception to automatically download formulas
8
13
  class FormulaIndexNotFoundError < GeneralError; end
14
+
15
+ class MainRepoNotFoundError < FormulaIndexNotFoundError; end
16
+
9
17
  class InvalidResourceError < GeneralError; end
18
+
10
19
  class LicensingError < GeneralError; end
20
+
11
21
  class ManifestCouldNotBeFoundError < GeneralError; end
22
+
12
23
  class ManifestCouldNotBeReadError < GeneralError; end
24
+
13
25
  class MissingAttributeError < GeneralError; end
26
+
27
+ class RepoNotFoundError < GeneralError; end
28
+
29
+ class RepoCouldNotBeUpdatedError < GeneralError; end
30
+
14
31
  class TamperedFileError < GeneralError; end
32
+
15
33
  class TimeoutError < GeneralError; end
34
+
16
35
  class UnknownFontTypeError < GeneralError; end
36
+
17
37
  class UnknownArchiveError < GeneralError; end
18
38
 
19
39
  class FontError < GeneralError