rosette-core 1.0.1

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