erratum 2.0.0 → 3.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5adebb18c185bba738d9ade01bb25b422874cec3
4
- data.tar.gz: 0c44bfaeca6bc92ecaaa1cdf0683ccb2bc0a5d13
3
+ metadata.gz: bcdf88a3d21177e27a3d39502aef4a053a0df0a4
4
+ data.tar.gz: fe5e579cc5677ceaa659a4153be16bd933de5b52
5
5
  SHA512:
6
- metadata.gz: 7111601d73851f7f06fa0afe8bbb7efeb83ffb3b1977aaf223200689d9074e772c7427ade962d6a42230adbaa6efa415a53d189adcdd63eaf602fec9c2227f92
7
- data.tar.gz: ffac65174a222d3ed9d1e5feb7472103d65946845de5955115a53328e6ac943d574f0a0ca6ef048afa471ef7274333101cde3d6588abf3adaa036b58f79ce6a6
6
+ metadata.gz: 993a890335e84d5277add854ca7cd60824e1a828116de2970cf8b239eb5e31b6b07c90526bb92cf6907a538ad1867ae3d2c81584effade2296ad1094694224c4
7
+ data.tar.gz: 35c74a023b357c73d21f7930f931a8592e7b6aa4ccfb4f65883350866ae995b489f2e20a1ec09b40f1ae1531e57b4ccc959f9ff568414eec8747e2ca166ec8ac
checksums.yaml.gz.sig CHANGED
Binary file
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'erratum/configuration'
4
+
5
+ module Erratum
6
+ module Configurable
7
+ module ClassMethods
8
+ def configure
9
+ yield configuration
10
+ end
11
+
12
+ def configuration
13
+ ::Erratum::Configuration.instance
14
+ end
15
+ end
16
+
17
+ def self.included(base)
18
+ base.extend(ClassMethods)
19
+ end
20
+
21
+ def configuration
22
+ ::Erratum::Configuration.instance
23
+ end
24
+ end
25
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'singleton'
4
4
 
5
- class Erratum
5
+ module Erratum
6
6
  class Configuration
7
7
  include Singleton
8
8
 
@@ -31,10 +31,6 @@ class Erratum
31
31
  end
32
32
  end
33
33
 
34
- def configuration
35
- Configuration.instance
36
- end
37
-
38
34
  def self.configure
39
35
  yield configuration
40
36
  end
data/lib/erratum/error.rb CHANGED
@@ -1,15 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'json'
4
- require 'erratum/configuration'
4
+ require 'erratum/configurable'
5
5
  require 'erratum/utilities/string'
6
6
 
7
- class Erratum
7
+ module Erratum
8
8
  module Error
9
+ include Configurable
10
+
9
11
  module ClassMethods
10
12
  def wrap(other)
11
- wrapped_error = new message: "#{other.class.name}: #{other.message}"
12
- wrapped_error.set_backtrace other.backtrace
13
+ wrapped_error = new(message: "#{other.class.name}: #{other.message}")
14
+ wrapped_error.set_backtrace(other.backtrace)
13
15
  wrapped_error
14
16
  end
15
17
  end
@@ -97,11 +99,5 @@ module Error
97
99
  def self.included(base)
98
100
  base.extend ClassMethods
99
101
  end
100
-
101
- private
102
-
103
- def configuration
104
- Erratum.configuration
105
- end
106
102
  end
107
103
  end
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'erratum/error'
4
-
5
- class Erratum
3
+ module Erratum
6
4
  module Errors
7
5
  module AuthenticationError
8
6
  end
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'erratum/error'
3
4
  require 'erratum/errors/authentication_error'
4
5
 
5
- class Erratum
6
+ module Erratum
6
7
  module Errors
7
8
  class DuplicateAuthenticationError < RuntimeError
8
9
  include Error
@@ -21,9 +22,11 @@ class DuplicateAuthenticationError < RuntimeError
21
22
  end
22
23
 
23
24
  def detail
24
- 'The authentication you attempted to register has already been registered by ' \
25
- 'another user. We do not currently support allowing multiple users to be connected ' \
26
- 'to the same authentication.'
25
+ <<~HEREDOC.chomp.tr("\n", ' ')
26
+ The authentication you attempted to register has already been registered
27
+ by another user. We do not currently support allowing multiple users to be
28
+ connected to the same authentication.
29
+ HEREDOC
27
30
  end
28
31
 
29
32
  def source
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'erratum/error'
3
4
  require 'erratum/errors/authentication_error'
4
5
 
5
- class Erratum
6
+ module Erratum
6
7
  module Errors
7
8
  class InvalidTokenError < RuntimeError
8
9
  include Error
@@ -19,8 +20,10 @@ class InvalidTokenError < RuntimeError
19
20
  end
20
21
 
21
22
  def detail
22
- 'The token you attempted to use for this request is invalid for this resource. ' \
23
- 'Please double-check and try again.'
23
+ <<~HEREDOC.chomp.tr("\n", ' ')
24
+ The token you attempted to use for this request is invalid for this resource.
25
+ Please double-check and try again.
26
+ HEREDOC
24
27
  end
25
28
 
26
29
  def source
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'erratum/error'
3
4
  require 'erratum/errors/authentication_error'
4
5
 
5
- class Erratum
6
+ module Erratum
6
7
  module Errors
7
8
  class InvalidUsernameOrPasswordError < RuntimeError
8
9
  include Error
@@ -19,8 +20,10 @@ class InvalidUsernameOrPasswordError < RuntimeError
19
20
  end
20
21
 
21
22
  def detail
22
- 'Either the username or password passed in or this request is invalid. Please ' \
23
- 'double-check and try again.'
23
+ <<~HEREDOC.chomp.tr("\n", ' ')
24
+ Either the username or password passed in or this request is invalid.
25
+ Please double-check and try again.
26
+ HEREDOC
24
27
  end
25
28
 
26
29
  def source
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'erratum/error'
4
-
5
- class Erratum
3
+ module Erratum
6
4
  module Errors
7
5
  module AuthorizationError
8
6
  end
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'erratum/error'
3
4
  require 'erratum/errors/authorization_error'
4
5
 
5
- class Erratum
6
+ module Erratum
6
7
  module Errors
7
8
  class ForbiddenError < RuntimeError
8
9
  include Error
@@ -29,8 +30,10 @@ class ForbiddenError < RuntimeError
29
30
  "#{action} the #{resource_name} with ID #{resource_id}"
30
31
  end
31
32
 
32
- "You do not have access to #{detail_quantity}. Providing a different set of " \
33
- "credentials may potentially allow you access to this resource."
33
+ <<~HEREDOC.chomp.tr("\n", ' ')
34
+ You do not have access to #{detail_quantity}. Providing a different set of
35
+ credentials may potentially allow you access to this resource.
36
+ HEREDOC
34
37
  end
35
38
 
36
39
  def source
@@ -1,16 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Erratum
3
+ module Erratum
4
4
  module Errors
5
5
  module CrudError
6
- attr_accessor :resource_name,
7
- :action,
8
- :resource_id
6
+ attr_accessor :action,
7
+ :resource_id,
8
+ :resource_name
9
9
 
10
- def initialize(resource_name: nil, action: nil, resource_id: nil, **args)
11
- self.resource_name = resource_name
12
- self.action = action || 'persist'
10
+ def initialize(action: 'persist', resource_id: nil, resource_name: nil, **args)
11
+ self.action = action
13
12
  self.resource_id = resource_id
13
+ self.resource_name = resource_name
14
14
 
15
15
  super(**args)
16
16
  end
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'erratum/error'
3
4
  require 'erratum/errors/crud_error'
4
5
 
5
- class Erratum
6
+ module Erratum
6
7
  module Errors
7
8
  class AssociationError < RuntimeError
8
9
  include Error
@@ -40,8 +41,10 @@ class AssociationError < RuntimeError
40
41
  end
41
42
 
42
43
  def detail
43
- "The #{association_name} that you attempted to associate with " \
44
- "the #{resource_name} was not valid."
44
+ <<~HEREDOC.chomp.tr("\n", ' ')
45
+ The #{association_name} that you attempted to associate with the
46
+ #{resource_name} was not valid.
47
+ HEREDOC
45
48
  end
46
49
 
47
50
  def source
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'erratum/error'
3
4
  require 'erratum/errors/crud_error'
4
5
 
5
- class Erratum
6
+ module Erratum
6
7
  module Errors
7
8
  class ResourceNotFoundError < RuntimeError
8
9
  include Error
@@ -37,8 +38,10 @@ class ResourceNotFoundError < RuntimeError
37
38
  end
38
39
 
39
40
  def detail
40
- "The #{resource_name} you attempted to #{action} for this request is either " \
41
- "not authorized for the authenticated user or does not exist."
41
+ <<~HEREDOC.chomp.tr("\n", ' ')
42
+ The #{resource_name} you attempted to #{action} for this request is either
43
+ not authorized for the authenticated user or does not exist.
44
+ HEREDOC
42
45
  end
43
46
 
44
47
  def source
@@ -3,7 +3,7 @@
3
3
  require 'erratum/error'
4
4
  require 'erratum/errors/crud_error'
5
5
 
6
- class Erratum
6
+ module Erratum
7
7
  module Errors
8
8
  class ResourcePersistenceError < RuntimeError
9
9
  include Error
@@ -40,8 +40,10 @@ class ResourcePersistenceError < RuntimeError
40
40
  end
41
41
 
42
42
  def detail
43
- @detail || "One or more of the attributes on the #{resource_name} you attempted " \
44
- "to #{action} is invalid."
43
+ @detail || <<~HEREDOC.chomp.tr("\n", ' ')
44
+ One or more of the attributes on the #{resource_name} you attempted to
45
+ #{action} is invalid.
46
+ HEREDOC
45
47
  end
46
48
 
47
49
  def source
@@ -1,6 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Erratum
3
+ require 'erratum/error'
4
+ require 'erratum/errors/crud_error'
5
+
6
+ module Erratum
4
7
  module Errors
5
8
  class ParameterMissingError < RuntimeError
6
9
  include Error
@@ -30,8 +33,10 @@ class ParameterMissingError < RuntimeError
30
33
  end
31
34
 
32
35
  def detail
33
- "When attempting to #{action} a #{resource_name}, '#{parameter}' is a " \
34
- "required parameter."
36
+ <<~HEREDOC.chomp.tr("\n", ' ')
37
+ When attempting to #{action} a #{resource_name}, '#{parameter}' is
38
+ a required parameter.
39
+ HEREDOC
35
40
  end
36
41
 
37
42
  def source
@@ -1,6 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Erratum
3
+ require 'erratum/error'
4
+ require 'erratum/errors/crud_error'
5
+
6
+ module Erratum
4
7
  module Errors
5
8
  class UnpermittedParametersError < RuntimeError
6
9
  include Error
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'erratum/resource_naming'
4
4
 
5
- class Erratum
5
+ module Erratum
6
6
  module RescuableResource
7
7
  def self.included(base)
8
8
  base.include ResourceNaming
@@ -13,10 +13,12 @@ module RescuableResource
13
13
  'ActiveRecord::InvalidForeignKey',
14
14
  'ActionController::ParameterMissing',
15
15
  'ActionController::UnpermittedParameters' do |exception|
16
- erratum = Erratum.convert(exception,
17
- resource_name: self.class.singular_resource_name,
18
- action: action_name)
19
- erratum = Array(erratum)
16
+
17
+ erratum = Array(
18
+ Erratum.convert(exception,
19
+ resource_name: self.class.singular_resource_name,
20
+ action: action_name),
21
+ )
20
22
 
21
23
  render json: Hash['errors' => erratum.as_json],
22
24
  status: erratum.first.http_status
@@ -1,32 +1,42 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Erratum
3
+ require 'erratum/utilities/string'
4
+
5
+ module Erratum
4
6
  module ResourceNaming
5
7
  CONTROLLER_RESOURCE_NAME_PATTERN = /\A((.*?::)?.*?)(\w+)Controller\z/
6
8
 
7
- module ClassMethods
8
- def plural_resource_name
9
- @plural_resource_name ||= name[CONTROLLER_RESOURCE_NAME_PATTERN, 3]
10
- .underscore
11
- .pluralize
12
- .downcase
13
- end
9
+ def plural_underscored_base_resource_name
10
+ @plural_underscored_base_resource_name ||= \
11
+ ::Erratum::Utilities::String.pluralize(
12
+ ::Erratum::Utilities::String.underscore(
13
+ plural_resource_base_class_name,
14
+ ),
15
+ )
16
+ .downcase
17
+ end
14
18
 
15
- def singular_resource_name
16
- @singular_resource_name ||= name[CONTROLLER_RESOURCE_NAME_PATTERN, 3]
17
- .underscore
18
- .singularize
19
- .downcase
20
- end
19
+ def singular_underscored_base_resource_name
20
+ @singular_underscored_base_resource_name ||= \
21
+ ::Erratum::Utilities::String.singularize(
22
+ ::Erratum::Utilities::String.underscore(
23
+ plural_resource_base_class_name,
24
+ ),
25
+ )
26
+ .downcase
27
+ end
21
28
 
22
- def resource_class_name
23
- @resource_class_name ||= singular_resource_name
24
- .camelize
25
- end
29
+ def singular_resource_base_class_name
30
+ @singular_resource_base_class_name ||= \
31
+ ::Erratum::Utilities::String
32
+ .singularize(plural_resource_base_class_name)
26
33
  end
27
34
 
28
- def self.included(base)
29
- base.extend ClassMethods
35
+ def plural_resource_base_class_name
36
+ @plural_resource_base_class_name ||= \
37
+ ::Erratum::Utilities::String.pluralize(
38
+ name[CONTROLLER_RESOURCE_NAME_PATTERN, 3],
39
+ )
30
40
  end
31
41
  end
32
42
  end
@@ -1,9 +1,137 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Erratum
3
+ module Erratum
4
4
  module Utilities
5
5
  class String
6
+ # rubocop:disable Style/PerlBackrefs
7
+ def self.camelize(other, uppercase_first_letter = true)
8
+ return unless other
9
+ return other.camelize if defined?(ActiveSupport::Inflector)
10
+
11
+ string = other.to_s
12
+
13
+ string = if uppercase_first_letter
14
+ string.sub(/^[a-z\d]*/, &:capitalize)
15
+ else
16
+ string.downcase
17
+ end
18
+
19
+ string.gsub!(%r{(?:_|(/))([a-z\d]*)}i) do
20
+ "#{$1}#{acronyms[$2] || $2.capitalize}"
21
+ end
22
+
23
+ string.gsub!('/', '::')
24
+
25
+ string
26
+ end
27
+ # rubocop:enable Style/PerlBackrefs
28
+
29
+ # rubocop:disable Metrics/MethodLength
30
+ def self.pluralize(other)
31
+ return unless other
32
+ return other.pluralize if defined?(ActiveSupport::Inflector)
33
+
34
+ result = other.to_s.dup
35
+
36
+ inflections = {
37
+ 'person' => 'people',
38
+ 'man' => 'men',
39
+ 'child' => 'children',
40
+ 'sex' => 'sexes',
41
+ 'move' => 'moves',
42
+ 'zombie' => 'zombies',
43
+ /(quiz)$/i => '\1zes',
44
+ /^(oxen)$/i => '\1',
45
+ /^(ox)$/i => '\1en',
46
+ /^(m|l)ice$/i => '\1ice',
47
+ /^(m|l)ouse$/i => '\1ice',
48
+ /(matr|vert|ind)(?:ix|ex)$/i => '\1ices',
49
+ /(x|ch|ss|sh)$/i => '\1es',
50
+ /([^aeiouy]|qu)y$/i => '\1ies',
51
+ /(hive)$/i => '\1s',
52
+ /(?:([^f])fe|([lr])f)$/i => '\1\2ves',
53
+ /sis$/i => 'ses',
54
+ /([ti])a$/i => '\1a',
55
+ /([ti])um$/i => '\1a',
56
+ /(buffal|tomat)o$/i => '\1oes',
57
+ /(bu)s$/i => '\1ses',
58
+ /(alias|status)$/i => '\1es',
59
+ /(octop|vir)i$/i => '\1i',
60
+ /(octop|vir)us$/i => '\1i',
61
+ /^(ax|test)is$/i => '\1es',
62
+ /s$/i => 's',
63
+ /$/ => 's',
64
+ }
65
+
66
+ inflections.each do |(rule, replacement)|
67
+ break if result.sub!(rule, replacement)
68
+ end
69
+
70
+ result
71
+ end
72
+ # rubocop:enable Metrics/MethodLength
73
+
74
+ # rubocop:disable Metrics/MethodLength, Metrics/AlignHash
75
+ def self.singularize(other)
76
+ return unless other
77
+ return other.singularize if defined?(ActiveSupport::Inflector)
78
+
79
+ result = other.to_s.dup
80
+
81
+ inflections = {
82
+ /(database)s$/i => '\1',
83
+ /(quiz)zes$/i => '\1',
84
+ /(matr)ices$/i => '\1ix',
85
+ /(vert|ind)ices$/i => '\1ex',
86
+ /^(ox)en/i => '\1',
87
+ /(alias|status)(es)?$/i => '\1',
88
+ /(octop|vir)(us|i)$/i => '\1us',
89
+ /^(a)x[ie]s$/i => '\1xis',
90
+ /(cris|test)(is|es)$/i => '\1is',
91
+ /(shoe)s$/i => '\1',
92
+ /(o)es$/i => '\1',
93
+ /(bus)(es)?$/i => '\1',
94
+ /^(m|l)ice$/i => '\1ouse',
95
+ /(x|ch|ss|sh)es$/i => '\1',
96
+ /(m)ovies$/i => '\1ovie',
97
+ /(s)eries$/i => '\1eries',
98
+ /([^aeiouy]|qu)ies$/i => '\1y',
99
+ /([lr])ves$/i => '\1f',
100
+ /(tive)s$/i => '\1',
101
+ /(hive)s$/i => '\1',
102
+ /([^f])ves$/i => '\1fe',
103
+ /(^analy)(sis|ses)$/i => '\1sis',
104
+ /
105
+ (
106
+ (a)naly |
107
+ (b)a |
108
+ (d)iagno |
109
+ (p)arenthe |
110
+ (p)rogno |
111
+ (s)ynop |
112
+ (t)he
113
+ )
114
+ (sis|ses)
115
+ $
116
+ /xi => '\1sis',
117
+ /([ti])a$/i => '\1um',
118
+ /(n)ews$/i => '\1ews',
119
+ /(ss)$/i => '\1',
120
+ /s$/i => '',
121
+ }
122
+
123
+ inflections.each do |(rule, replacement)|
124
+ break if result.sub!(rule, replacement)
125
+ end
126
+
127
+ result
128
+ end
129
+ # rubocop:enable Metrics/MethodLength, Metrics/AlignHash
130
+
6
131
  def self.underscore(other)
132
+ return unless other
133
+ return other.underscore if defined?(ActiveSupport::Inflector)
134
+
7
135
  word = other.to_s.gsub('::', '/')
8
136
  word.gsub!(/(?:([A-Za-z\d])|^)(?=\b|[^a-z])/) do
9
137
  "#{Regexp.last_match(1)}#{Regexp.last_match(1) && ''}"
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'erratum/resource_naming'
4
4
 
5
- class Erratum
5
+ module Erratum
6
6
  module VerifiableResource
7
7
  def self.included(base)
8
8
  base.include ResourceNaming
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Erratum
4
- VERSION = '2.0.0'
3
+ module Erratum
4
+ VERSION = '3.0.0'
5
5
  end
data/lib/erratum.rb CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  require 'erratum/configuration'
4
4
  require 'erratum/error'
5
- require 'erratum/errors/authorization_error'
6
- require 'erratum/errors/authorization_errors/forbidden_error'
7
5
  require 'erratum/errors/authentication_error'
8
6
  require 'erratum/errors/authentication_errors/duplicate_authentication_error'
9
7
  require 'erratum/errors/authentication_errors/invalid_token_error'
10
8
  require 'erratum/errors/authentication_errors/invalid_username_or_password_error'
9
+ require 'erratum/errors/authorization_error'
10
+ require 'erratum/errors/authorization_errors/forbidden_error'
11
11
  require 'erratum/errors/crud_error'
12
12
  require 'erratum/errors/crud_errors/association_error'
13
13
  require 'erratum/errors/crud_errors/resource_not_found_error'
@@ -18,7 +18,7 @@ require 'erratum/rescuable_resource'
18
18
  require 'erratum/verifiable_resource'
19
19
  require 'erratum/version'
20
20
 
21
- class Erratum
21
+ module Erratum
22
22
  def self.fetch(error_type)
23
23
  Object.const_get("Erratum::Errors::#{error_type}")
24
24
  end
data.tar.gz.sig CHANGED
@@ -1,5 +1 @@
1
- o\)[,��v�`r��=d'����`x�:�)OBRjj,������l��a8�R)R�X��k J�'hX��
2
- �0�&�<��"xߴn{�.D�ݫ �Le���&?��X�=M��УV��#oD1=�rJ
3
- �3#��vB�[3�)c�=���^�Z�|8�����MG{o�1��[�ՊV�����
4
- ��]z��,5�Q���wu"00S&%���m6;��X�W�P �IP:d:�>�HP��\�؀
5
- W���.��m
1
+ i�����Q�i&τ��<�L��f����fpG�\�W�����b&�׍��y�h��i������U�.�-ֶP��"o�$��#��0��Y��#K�����5�!�]Z�|��B�x㐜�~_��n�!������w��9,%��`xc��9E3 L1]ѣ
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: erratum
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - thegranddesign
@@ -31,7 +31,7 @@ cert_chain:
31
31
  Y2GAoHKstmfIVhc4XHOPpmTd2o/C29O9oaRgjrkfQEhF/KvJ/PhoV5hvokzsCyI5
32
32
  iUeXPfvrGD/itYIBCgk+fnzyQQ4QtE5hTQaWQ3o2
33
33
  -----END CERTIFICATE-----
34
- date: 2018-01-24 00:00:00.000000000 Z
34
+ date: 2018-04-24 00:00:00.000000000 Z
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
@@ -111,6 +111,7 @@ files:
111
111
  - LICENSE.txt
112
112
  - README.md
113
113
  - lib/erratum.rb
114
+ - lib/erratum/configurable.rb
114
115
  - lib/erratum/configuration.rb
115
116
  - lib/erratum/error.rb
116
117
  - lib/erratum/errors/authentication_error.rb
metadata.gz.sig CHANGED
Binary file