rosette-core 1.0.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.
Files changed (158) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +26 -0
  3. data/History.txt +3 -0
  4. data/README.md +94 -0
  5. data/Rakefile +18 -0
  6. data/lib/rosette/core.rb +110 -0
  7. data/lib/rosette/core/branch_utils.rb +152 -0
  8. data/lib/rosette/core/commands.rb +139 -0
  9. data/lib/rosette/core/commands/errors.rb +17 -0
  10. data/lib/rosette/core/commands/git/commit_command.rb +65 -0
  11. data/lib/rosette/core/commands/git/diff_base_command.rb +301 -0
  12. data/lib/rosette/core/commands/git/diff_command.rb +188 -0
  13. data/lib/rosette/core/commands/git/diff_entry.rb +44 -0
  14. data/lib/rosette/core/commands/git/fetch_command.rb +27 -0
  15. data/lib/rosette/core/commands/git/repo_snapshot_command.rb +40 -0
  16. data/lib/rosette/core/commands/git/show_command.rb +70 -0
  17. data/lib/rosette/core/commands/git/snapshot_command.rb +50 -0
  18. data/lib/rosette/core/commands/git/status_command.rb +128 -0
  19. data/lib/rosette/core/commands/git/with_non_merge_ref.rb +48 -0
  20. data/lib/rosette/core/commands/git/with_ref.rb +92 -0
  21. data/lib/rosette/core/commands/git/with_refs.rb +92 -0
  22. data/lib/rosette/core/commands/git/with_repo_name.rb +50 -0
  23. data/lib/rosette/core/commands/git/with_snapshots.rb +45 -0
  24. data/lib/rosette/core/commands/queuing/enqueue_commit_command.rb +37 -0
  25. data/lib/rosette/core/commands/queuing/requeue_commit_command.rb +46 -0
  26. data/lib/rosette/core/commands/translations/export_command.rb +257 -0
  27. data/lib/rosette/core/commands/translations/translation_lookup_command.rb +66 -0
  28. data/lib/rosette/core/commands/translations/with_locale.rb +47 -0
  29. data/lib/rosette/core/configurator.rb +160 -0
  30. data/lib/rosette/core/error_reporters/buffered_error_reporter.rb +96 -0
  31. data/lib/rosette/core/error_reporters/error_reporter.rb +31 -0
  32. data/lib/rosette/core/error_reporters/nil_error_reporter.rb +25 -0
  33. data/lib/rosette/core/error_reporters/printing_error_reporter.rb +58 -0
  34. data/lib/rosette/core/error_reporters/raising_error_reporter.rb +27 -0
  35. data/lib/rosette/core/errors.rb +93 -0
  36. data/lib/rosette/core/extractor/commit_log.rb +33 -0
  37. data/lib/rosette/core/extractor/commit_log_status.rb +57 -0
  38. data/lib/rosette/core/extractor/commit_processor.rb +109 -0
  39. data/lib/rosette/core/extractor/extractor.rb +72 -0
  40. data/lib/rosette/core/extractor/extractor_config.rb +74 -0
  41. data/lib/rosette/core/extractor/locale.rb +118 -0
  42. data/lib/rosette/core/extractor/phrase.rb +76 -0
  43. data/lib/rosette/core/extractor/phrase/phrase_index_policy.rb +108 -0
  44. data/lib/rosette/core/extractor/phrase/phrase_to_hash.rb +33 -0
  45. data/lib/rosette/core/extractor/repo_config.rb +339 -0
  46. data/lib/rosette/core/extractor/serializer_config.rb +55 -0
  47. data/lib/rosette/core/extractor/static_extractor.rb +44 -0
  48. data/lib/rosette/core/extractor/translation.rb +44 -0
  49. data/lib/rosette/core/extractor/translation/translation_to_hash.rb +28 -0
  50. data/lib/rosette/core/git/diff_finder.rb +131 -0
  51. data/lib/rosette/core/git/ref.rb +116 -0
  52. data/lib/rosette/core/git/repo.rb +378 -0
  53. data/lib/rosette/core/path_matcher_factory.rb +330 -0
  54. data/lib/rosette/core/resolvers/extractor_id.rb +37 -0
  55. data/lib/rosette/core/resolvers/integration_id.rb +37 -0
  56. data/lib/rosette/core/resolvers/preprocessor_id.rb +38 -0
  57. data/lib/rosette/core/resolvers/resolver.rb +115 -0
  58. data/lib/rosette/core/resolvers/serializer_id.rb +37 -0
  59. data/lib/rosette/core/snapshots/cached_head_snapshot_factory.rb +51 -0
  60. data/lib/rosette/core/snapshots/cached_snapshot_factory.rb +67 -0
  61. data/lib/rosette/core/snapshots/head_snapshot_factory.rb +58 -0
  62. data/lib/rosette/core/snapshots/repo_config_path_filter.rb +83 -0
  63. data/lib/rosette/core/snapshots/snapshot_factory.rb +184 -0
  64. data/lib/rosette/core/string_utils.rb +23 -0
  65. data/lib/rosette/core/translation_status.rb +81 -0
  66. data/lib/rosette/core/validators.rb +18 -0
  67. data/lib/rosette/core/validators/commit_validator.rb +62 -0
  68. data/lib/rosette/core/validators/commits_validator.rb +32 -0
  69. data/lib/rosette/core/validators/encoding_validator.rb +32 -0
  70. data/lib/rosette/core/validators/locale_validator.rb +37 -0
  71. data/lib/rosette/core/validators/repo_validator.rb +33 -0
  72. data/lib/rosette/core/validators/serializer_validator.rb +37 -0
  73. data/lib/rosette/core/validators/validator.rb +31 -0
  74. data/lib/rosette/core/version.rb +8 -0
  75. data/lib/rosette/data_stores.rb +11 -0
  76. data/lib/rosette/data_stores/errors.rb +26 -0
  77. data/lib/rosette/data_stores/phrase_status.rb +59 -0
  78. data/lib/rosette/integrations.rb +12 -0
  79. data/lib/rosette/integrations/errors.rb +15 -0
  80. data/lib/rosette/integrations/integratable.rb +58 -0
  81. data/lib/rosette/integrations/integration.rb +23 -0
  82. data/lib/rosette/preprocessors.rb +11 -0
  83. data/lib/rosette/preprocessors/errors.rb +14 -0
  84. data/lib/rosette/preprocessors/preprocessor.rb +48 -0
  85. data/lib/rosette/queuing.rb +14 -0
  86. data/lib/rosette/queuing/commits.rb +19 -0
  87. data/lib/rosette/queuing/commits/commit_conductor.rb +90 -0
  88. data/lib/rosette/queuing/commits/commit_job.rb +93 -0
  89. data/lib/rosette/queuing/commits/commits_queue_configurator.rb +60 -0
  90. data/lib/rosette/queuing/commits/extract_stage.rb +46 -0
  91. data/lib/rosette/queuing/commits/fetch_stage.rb +51 -0
  92. data/lib/rosette/queuing/commits/finalize_stage.rb +76 -0
  93. data/lib/rosette/queuing/commits/phrase_storage_granularity.rb +20 -0
  94. data/lib/rosette/queuing/commits/push_stage.rb +91 -0
  95. data/lib/rosette/queuing/commits/stage.rb +96 -0
  96. data/lib/rosette/queuing/job.rb +74 -0
  97. data/lib/rosette/queuing/queue.rb +28 -0
  98. data/lib/rosette/queuing/queue_configurator.rb +76 -0
  99. data/lib/rosette/queuing/worker.rb +30 -0
  100. data/lib/rosette/serializers.rb +10 -0
  101. data/lib/rosette/serializers/serializer.rb +98 -0
  102. data/lib/rosette/tms.rb +9 -0
  103. data/lib/rosette/tms/repository.rb +95 -0
  104. data/rosette-core.gemspec +24 -0
  105. data/spec/core/branch_utils_spec.rb +110 -0
  106. data/spec/core/commands/git/commit_command_spec.rb +60 -0
  107. data/spec/core/commands/git/diff_command_spec.rb +263 -0
  108. data/spec/core/commands/git/fetch_command_spec.rb +61 -0
  109. data/spec/core/commands/git/repo_snapshot_command_spec.rb +72 -0
  110. data/spec/core/commands/git/show_command_spec.rb +128 -0
  111. data/spec/core/commands/git/snapshot_command_spec.rb +86 -0
  112. data/spec/core/commands/git/status_command_spec.rb +154 -0
  113. data/spec/core/commands/queuing/enqueue_commit_command_spec.rb +34 -0
  114. data/spec/core/commands/queuing/requeue_commit_command_spec.rb +46 -0
  115. data/spec/core/commands/translations/export_command_spec.rb +113 -0
  116. data/spec/core/commands/translations/translation_lookup_command_spec.rb +58 -0
  117. data/spec/core/configurator_spec.rb +47 -0
  118. data/spec/core/error_reporters/buffered_error_reporter_spec.rb +61 -0
  119. data/spec/core/error_reporters/nil_error_reporter_spec.rb +16 -0
  120. data/spec/core/error_reporters/printing_error_reporter_spec.rb +60 -0
  121. data/spec/core/extractor/commit_log_status_spec.rb +216 -0
  122. data/spec/core/extractor/commit_processor_spec.rb +68 -0
  123. data/spec/core/extractor/extractor_config_spec.rb +47 -0
  124. data/spec/core/extractor/extractor_spec.rb +26 -0
  125. data/spec/core/extractor/locale_spec.rb +92 -0
  126. data/spec/core/extractor/phrase/phrase_index_policy_spec.rb +116 -0
  127. data/spec/core/extractor/phrase/phrase_to_hash_spec.rb +18 -0
  128. data/spec/core/extractor/repo_config_spec.rb +147 -0
  129. data/spec/core/extractor/translation/translation_to_hash_spec.rb +25 -0
  130. data/spec/core/git/diff_finder_spec.rb +74 -0
  131. data/spec/core/git/ref_spec.rb +118 -0
  132. data/spec/core/git/repo_spec.rb +216 -0
  133. data/spec/core/path_matcher_factory_spec.rb +139 -0
  134. data/spec/core/resolvers/extractor_id_spec.rb +47 -0
  135. data/spec/core/resolvers/integration_id_spec.rb +47 -0
  136. data/spec/core/resolvers/preprocessor_id_spec.rb +47 -0
  137. data/spec/core/resolvers/serializer_id_spec.rb +47 -0
  138. data/spec/core/snapshots/snapshot_factory_spec.rb +145 -0
  139. data/spec/core/string_utils_spec.rb +19 -0
  140. data/spec/core/translation_status_spec.rb +91 -0
  141. data/spec/core/validators/commit_validator_spec.rb +40 -0
  142. data/spec/core/validators/encoding_validator_spec.rb +30 -0
  143. data/spec/core/validators/locale_validator_spec.rb +31 -0
  144. data/spec/core/validators/repo_validator_spec.rb +30 -0
  145. data/spec/core/validators/serializer_validator_spec.rb +31 -0
  146. data/spec/integrations/integratable_spec.rb +58 -0
  147. data/spec/queuing/commits/commit_conductor_spec.rb +71 -0
  148. data/spec/queuing/commits/commit_job_spec.rb +87 -0
  149. data/spec/queuing/commits/extract_stage_spec.rb +68 -0
  150. data/spec/queuing/commits/fetch_stage_spec.rb +101 -0
  151. data/spec/queuing/commits/finalize_stage_spec.rb +88 -0
  152. data/spec/queuing/commits/push_stage_spec.rb +145 -0
  153. data/spec/queuing/commits/stage_spec.rb +80 -0
  154. data/spec/queuing/job_spec.rb +33 -0
  155. data/spec/queuing/queue_configurator_spec.rb +44 -0
  156. data/spec/spec_helper.rb +90 -0
  157. data/spec/test_helpers/fake_commit_stage.rb +17 -0
  158. metadata +257 -0
@@ -0,0 +1,66 @@
1
+ # encoding: UTF-8
2
+
3
+ module Rosette
4
+ module Core
5
+ module Commands
6
+
7
+ # Returns the translation for the given phrase and locale combination.
8
+ #
9
+ # @!attribute [r] locale
10
+ # @return [String] the locale to export translations for.
11
+ #
12
+ # @example
13
+ # cmd = TranslationLookupCommand.new(configuration)
14
+ # .set_repo_name('my_repo')
15
+ # .set_locale('es')
16
+ # .set_meta_key('my.phrase')
17
+ # .set_key('I am a phrase')
18
+ #
19
+ # cmd.execute
20
+ # # => "Soy una frase"
21
+ #
22
+ # @!attribute [r] locale
23
+ # @return [String] the locale of the translation to look up.
24
+ # @!attribute [r] repo_name
25
+ # @return [String] the name of the repo the phrase (and therefore the
26
+ # translation) belongs to.
27
+ # @!attribute [r] key
28
+ # @return [String] the phrase key.
29
+ # @!attribute [r] meta_key
30
+ # @return [String] the phrase meta key.
31
+ class TranslationLookupCommand < GitCommand
32
+ attr_reader :key, :meta_key
33
+
34
+ include WithRepoName
35
+ include WithRef
36
+ include WithLocale
37
+
38
+ def set_key(key)
39
+ @key = key
40
+ self
41
+ end
42
+
43
+ def set_meta_key(meta_key)
44
+ @meta_key = meta_key
45
+ self
46
+ end
47
+
48
+ def execute
49
+ phrase = datastore.lookup_phrase(repo_name, key, meta_key, commit_id)
50
+ repo_config.tms.lookup_translation(locale_obj, phrase)
51
+ end
52
+
53
+ protected
54
+
55
+ def repo_config
56
+ configuration.get_repo(repo_name)
57
+ end
58
+
59
+ def locale_obj
60
+ repo_config.locales.find { |l| l.code == locale }
61
+ end
62
+ end
63
+
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,47 @@
1
+ # encoding: UTF-8
2
+
3
+ module Rosette
4
+ module Core
5
+ module Commands
6
+
7
+ # Mixin that handles configuration and validation of a locale code.
8
+ # Meant to be mixed into the classes in {Rosette::Core::Commands}.
9
+ #
10
+ # @example
11
+ # class MyCommand < Command
12
+ # include WithRepoName
13
+ # include WithLocale
14
+ # end
15
+ #
16
+ # cmd = MyCommand.new(configuration)
17
+ # .set_repo_name('my_repo')
18
+ # .set_locale('ja-JP')
19
+ #
20
+ # cmd.locale # => 'ja-JP'
21
+ # cmd.valid? # => true
22
+ #
23
+ # cmd.set_locale('foobar')
24
+ # cmd.valid? # => false
25
+ # cmd.messages # => { locale: ["Repo 'my_repo' doesn't support the 'foobar' locale"] }
26
+ module WithLocale
27
+ attr_reader :locale
28
+
29
+ # Sets the locale code.
30
+ #
31
+ # @param [String] locale_code
32
+ # @return [self]
33
+ def set_locale(locale_code)
34
+ @locale = locale_code
35
+ self
36
+ end
37
+
38
+ protected
39
+
40
+ def self.included(base)
41
+ base.validate :locale, type: :locale
42
+ end
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,160 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'active_support'
4
+ require 'rosette/integrations'
5
+
6
+ module Rosette
7
+ module Core
8
+
9
+ # Builds Rosette configuration. Usually used via +Rosette#build_config+.
10
+ #
11
+ # @see Rosette
12
+ #
13
+ # @example
14
+ # config = Rosette.build_config do |config|
15
+ # config.add_repo do |repo_config|
16
+ # ...
17
+ # end
18
+ # end
19
+ #
20
+ # @!attribute [r] repo_configs
21
+ # @return [Array<RepoConfig>] The current array of configured repo
22
+ # configs.
23
+ # @!attribute [r] datastore
24
+ # @return [DataStore] The datastore to store phrases and translations in.
25
+ # @!attribute [r] cache
26
+ # @return [#fetch] The cache instance to use (can be +nil+).
27
+ # @!attribute [r] queue
28
+ # @return [Rosette::Queuing::Queue] The queue implementation to use.
29
+ # @!attribute [r] error_reporter
30
+ # @return [ErrorReporter] The error reporter to use if errors occur.
31
+ class Configurator
32
+ include Integrations::Integratable
33
+
34
+ attr_reader :repo_configs, :datastore, :cache, :queue, :error_reporter
35
+
36
+ # Creates a new config object.
37
+ def initialize
38
+ @repo_configs = []
39
+ @integrations = []
40
+ @cache = ActiveSupport::Cache.lookup_store
41
+ @error_reporter ||= PrintingErrorReporter.new(STDOUT)
42
+ end
43
+
44
+ # Adds a repo config.
45
+ #
46
+ # @param [String] name The semantic name of the repo.
47
+ # @return [void]
48
+ def add_repo(name)
49
+ repo_configs << Rosette::Core::RepoConfig.new(name, self).tap do |repo_config|
50
+ yield repo_config
51
+ repo_config.apply_integrations(repo_config)
52
+ end
53
+ end
54
+
55
+ # Retrieve a repo config by name.
56
+ #
57
+ # @param [String] name The semantic name of the repo to retrieve.
58
+ # @return [RepoConfig]
59
+ def get_repo(name)
60
+ repo_configs.find { |rc| rc.name == name }
61
+ end
62
+
63
+ # Set the datastore to use to store phrases and translations.
64
+ #
65
+ # @param [Const, String] datastore The datastore to use. When this
66
+ # parameter is a string, +use_datastore+ will try to look up the
67
+ # corresponding constant with a "DataStore" suffix. If it's a constant
68
+ # instead, the constant is used without modifications.
69
+ # @param [Hash] options A hash of options passed to the datastore's
70
+ # constructor.
71
+ # @return [void]
72
+ def use_datastore(datastore, options = {})
73
+ const = case datastore
74
+ when String
75
+ if const = find_datastore_const(datastore)
76
+ const
77
+ else
78
+ raise ArgumentError, "'#{datastore}' couldn't be found."
79
+ end
80
+ when Class
81
+ datastore
82
+ else
83
+ raise ArgumentError, "'#{datastore}' must be a String or Class."
84
+ end
85
+
86
+ @datastore = const.new(options)
87
+ nil
88
+ end
89
+
90
+ # Set the error reporter this config should use to report errors. The
91
+ # default error reporter is an instance of {PrintingErrorReporter}.
92
+ #
93
+ # @param [ErrorReporter] reporter The error reporter.
94
+ # @return [void]
95
+ def use_error_reporter(reporter)
96
+ @error_reporter = reporter
97
+ end
98
+
99
+ # Set the cache implementation. This must be one of the offerings in
100
+ # +ActiveSupport::Cache+:
101
+ # http://api.rubyonrails.org/classes/ActiveSupport/Cache.html
102
+ #
103
+ # @param [*] args The args to pass to ActiveSupport::Cache#lookup_store:
104
+ # http://api.rubyonrails.org/classes/ActiveSupport/Cache.html#method-c-lookup_store
105
+ # @return [void]
106
+ def use_cache(*args)
107
+ @cache = ActiveSupport::Cache.lookup_store(args)
108
+ end
109
+
110
+ # Set the queue implementation. Queues must implement the
111
+ # [Rosette::Queuing::Queue] interface.
112
+ #
113
+ # @param [Const, String] queue The queue to use. When this parameter
114
+ # is a string, +use_queue+ will try to look up the corresponding
115
+ # constant with a "Queue" suffix. If it's a constant instead, the
116
+ # constant is used without modifications.
117
+ # @param [Hash] options A hash of options passed to the queue's
118
+ # constructor.
119
+ # @return [void]
120
+ def use_queue(queue)
121
+ const = case queue
122
+ when String
123
+ if const = find_queue_const(queue)
124
+ const
125
+ else
126
+ raise ArgumentError, "'#{queue}' couldn't be found."
127
+ end
128
+ when Class
129
+ queue
130
+ else
131
+ raise ArgumentError, "'#{queue}' must be a String or Class."
132
+ end
133
+
134
+ configurator = Rosette::Queuing::QueueConfigurator.new
135
+ yield configurator if block_given?
136
+ @queue = const.new(configurator)
137
+ nil
138
+ end
139
+
140
+ private
141
+
142
+ def find_datastore_const(name)
143
+ const_str = "#{Rosette::Core::StringUtils.camelize(name)}DataStore"
144
+
145
+ if Rosette::DataStores.const_defined?(const_str)
146
+ Rosette::DataStores.const_get(const_str)
147
+ end
148
+ end
149
+
150
+ def find_queue_const(name)
151
+ const_str = "#{Rosette::Core::StringUtils.camelize(name)}Queue"
152
+
153
+ if Rosette::Queuing.const_defined?(const_str)
154
+ Rosette::Queuing.const_get(const_str)::Queue
155
+ end
156
+ end
157
+ end
158
+
159
+ end
160
+ end
@@ -0,0 +1,96 @@
1
+ # encoding: UTF-8
2
+
3
+ module Rosette
4
+ module Core
5
+
6
+ # Stores warnings errors in an internal buffer.
7
+ #
8
+ # @!attribute [r] errors
9
+ # @return [Array<Exception>] the list of collected errors.
10
+ # @!attribute [r] warnings
11
+ # @return [Array<Exception>] the list of collected warnings.
12
+ class BufferedErrorReporter < ErrorReporter
13
+ attr_reader :errors, :warnings
14
+
15
+ def initialize
16
+ reset
17
+ end
18
+
19
+ # Add an error object to the list of collected errors.
20
+ #
21
+ # @param [Exception] error The error object to add.
22
+ # @param [Hash] options A hash of options to record with the error.
23
+ # @return [void]
24
+ def report_error(error, options = {})
25
+ errors << { error: error, options: options }
26
+ end
27
+
28
+ # Add an error object to the list of collected warnings.
29
+ #
30
+ # @param [Exception] error The error object to add.
31
+ # @param [Hash] options A hash of options to record with the error.
32
+ # @return [void]
33
+ def report_warning(error, options = {})
34
+ warnings << { error: error, options: options }
35
+ end
36
+
37
+ # Clears all errors and warnings
38
+ #
39
+ # @return [void]
40
+ def reset
41
+ @errors = []
42
+ @warnings = []
43
+ end
44
+
45
+ # Returns true if one or more errors has been added, false otherwise.
46
+ #
47
+ # @return [Boolean] Whether or not one or more errors have been added.
48
+ def errors_found?
49
+ errors.size > 0
50
+ end
51
+
52
+ # Returns true if one or more warnings has been added, false otherwise.
53
+ #
54
+ # @return [Boolean] Whether or not one or more errors have been added.
55
+ def warnings_found?
56
+ warnings.size > 0
57
+ end
58
+
59
+ # Iterates over and yields each error. If no block is given, returns
60
+ # an +Enumerator+.
61
+ #
62
+ # @yield [error, options] each consecutive error and options hash.
63
+ # @yieldparam warning [Exception] the error
64
+ # @yieldparam options [Hash] the hash of options associated with +error+
65
+ # @return [nil, Enumerator] +nil+ if no block is given, an +Enumerator+
66
+ # otherwise.
67
+ def each_error(&block)
68
+ if block_given?
69
+ errors.each do |error_hash|
70
+ yield error_hash[:error], error_hash[:options]
71
+ end
72
+ else
73
+ to_enum(__method__)
74
+ end
75
+ end
76
+
77
+ # Iterates over and yields each warning. If no block is given, returns
78
+ # an +Enumerator+.
79
+ #
80
+ # @yield [warning, options] each consecutive warning and options hash.
81
+ # @yieldparam warning [Exception] the warning
82
+ # @yieldparam options [Hash] the hash of options associated with +warning+
83
+ # @return [nil, Enumerator] +nil+ if no block is given, an +Enumerator+
84
+ def each_warning(&block)
85
+ if block_given?
86
+ warnings.each do |warning_hash|
87
+ yield warning_hash[:error], warning_hash[:options]
88
+ end
89
+ else
90
+ to_enum(__method__)
91
+ end
92
+ end
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: UTF-8
2
+
3
+ module Rosette
4
+ module Core
5
+
6
+ # Error reporter interface.
7
+ class ErrorReporter
8
+ # Report an error.
9
+ #
10
+ # @raise [NotImplementedError]
11
+ def report_error(error, options = {})
12
+ raise NotImplementedError, 'Please use a derived class.'
13
+ end
14
+
15
+ # Report a warning.
16
+ #
17
+ # @raise [NotImplementedError]
18
+ def report_warning(error, options = {})
19
+ raise NotImplementedError, 'Please use a derived class.'
20
+ end
21
+
22
+ # Catch errors raised by the block and report them.
23
+ def with_error_reporting
24
+ yield
25
+ rescue Exception => e
26
+ report_error(e)
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: UTF-8
2
+
3
+ module Rosette
4
+ module Core
5
+
6
+ # An error reporter that does nothing.
7
+ class NilErrorReporter < ErrorReporter
8
+ # Get a reference to the only instance of +NilErrorReporter+.
9
+ #
10
+ # @return [NilErrorReporter] the only instance of +NilErrorReporter+.
11
+ def self.instance
12
+ @instance ||= new
13
+ end
14
+
15
+ # Does nothing.
16
+ # @return [nil]
17
+ def report_error(error, options = {}); end
18
+
19
+ # Does nothing.
20
+ # @return [nil]
21
+ def report_warning(error, options = {}); end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,58 @@
1
+ # encoding: UTF-8
2
+
3
+ module Rosette
4
+ module Core
5
+
6
+ # Prints errors.
7
+ #
8
+ # @!attribute [r] stream
9
+ # @return [#write] a stream-like object to print errors to.
10
+ # @!attribute [r] print_stack_trace
11
+ # @return [Boolean] whether or not to print a stack trace along with
12
+ # the error message.
13
+ class PrintingErrorReporter < ErrorReporter
14
+ attr_reader :stream, :print_stack_trace
15
+ alias :print_stack_trace? :print_stack_trace
16
+
17
+ # Creates a new error reporter.
18
+ #
19
+ # @param [#write] stream The stream-like object to print errors to.
20
+ # @param [Hash] options A hash of options. Can contain:
21
+ # * +print_stack_trace+: A boolean value indicating whether or not
22
+ # a stack trace should be printed alongside the error message.
23
+ def initialize(stream, options = {})
24
+ @stream = stream
25
+ @print_stack_trace = options.fetch(:print_stack_trace, false)
26
+ end
27
+
28
+ # Print an error.
29
+ #
30
+ # @param [Exception] error The error to print.
31
+ # @param [Hash] options A hash of associated options (will also be
32
+ # printed)
33
+ # @return [void]
34
+ def report_error(error, options = {})
35
+ stream.write("#{error.message}\n")
36
+
37
+ if print_stack_trace?
38
+ Array(error.backtrace).each do |line|
39
+ stream.write("#{line}\n")
40
+ end
41
+
42
+ stream.write(options.inspect)
43
+ end
44
+ end
45
+
46
+ # Print a warning. Warnings are treated the same as errors.
47
+ #
48
+ # @param [Exception] error The error to print.
49
+ # @param [Hash] options A hash of associated options (will also be
50
+ # printed)
51
+ # @return [void]
52
+ def report_warning(error, options = {})
53
+ report_error(error, options)
54
+ end
55
+ end
56
+
57
+ end
58
+ end