rosette-core 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +26 -0
- data/History.txt +3 -0
- data/README.md +94 -0
- data/Rakefile +18 -0
- data/lib/rosette/core.rb +110 -0
- data/lib/rosette/core/branch_utils.rb +152 -0
- data/lib/rosette/core/commands.rb +139 -0
- data/lib/rosette/core/commands/errors.rb +17 -0
- data/lib/rosette/core/commands/git/commit_command.rb +65 -0
- data/lib/rosette/core/commands/git/diff_base_command.rb +301 -0
- data/lib/rosette/core/commands/git/diff_command.rb +188 -0
- data/lib/rosette/core/commands/git/diff_entry.rb +44 -0
- data/lib/rosette/core/commands/git/fetch_command.rb +27 -0
- data/lib/rosette/core/commands/git/repo_snapshot_command.rb +40 -0
- data/lib/rosette/core/commands/git/show_command.rb +70 -0
- data/lib/rosette/core/commands/git/snapshot_command.rb +50 -0
- data/lib/rosette/core/commands/git/status_command.rb +128 -0
- data/lib/rosette/core/commands/git/with_non_merge_ref.rb +48 -0
- data/lib/rosette/core/commands/git/with_ref.rb +92 -0
- data/lib/rosette/core/commands/git/with_refs.rb +92 -0
- data/lib/rosette/core/commands/git/with_repo_name.rb +50 -0
- data/lib/rosette/core/commands/git/with_snapshots.rb +45 -0
- data/lib/rosette/core/commands/queuing/enqueue_commit_command.rb +37 -0
- data/lib/rosette/core/commands/queuing/requeue_commit_command.rb +46 -0
- data/lib/rosette/core/commands/translations/export_command.rb +257 -0
- data/lib/rosette/core/commands/translations/translation_lookup_command.rb +66 -0
- data/lib/rosette/core/commands/translations/with_locale.rb +47 -0
- data/lib/rosette/core/configurator.rb +160 -0
- data/lib/rosette/core/error_reporters/buffered_error_reporter.rb +96 -0
- data/lib/rosette/core/error_reporters/error_reporter.rb +31 -0
- data/lib/rosette/core/error_reporters/nil_error_reporter.rb +25 -0
- data/lib/rosette/core/error_reporters/printing_error_reporter.rb +58 -0
- data/lib/rosette/core/error_reporters/raising_error_reporter.rb +27 -0
- data/lib/rosette/core/errors.rb +93 -0
- data/lib/rosette/core/extractor/commit_log.rb +33 -0
- data/lib/rosette/core/extractor/commit_log_status.rb +57 -0
- data/lib/rosette/core/extractor/commit_processor.rb +109 -0
- data/lib/rosette/core/extractor/extractor.rb +72 -0
- data/lib/rosette/core/extractor/extractor_config.rb +74 -0
- data/lib/rosette/core/extractor/locale.rb +118 -0
- data/lib/rosette/core/extractor/phrase.rb +76 -0
- data/lib/rosette/core/extractor/phrase/phrase_index_policy.rb +108 -0
- data/lib/rosette/core/extractor/phrase/phrase_to_hash.rb +33 -0
- data/lib/rosette/core/extractor/repo_config.rb +339 -0
- data/lib/rosette/core/extractor/serializer_config.rb +55 -0
- data/lib/rosette/core/extractor/static_extractor.rb +44 -0
- data/lib/rosette/core/extractor/translation.rb +44 -0
- data/lib/rosette/core/extractor/translation/translation_to_hash.rb +28 -0
- data/lib/rosette/core/git/diff_finder.rb +131 -0
- data/lib/rosette/core/git/ref.rb +116 -0
- data/lib/rosette/core/git/repo.rb +378 -0
- data/lib/rosette/core/path_matcher_factory.rb +330 -0
- data/lib/rosette/core/resolvers/extractor_id.rb +37 -0
- data/lib/rosette/core/resolvers/integration_id.rb +37 -0
- data/lib/rosette/core/resolvers/preprocessor_id.rb +38 -0
- data/lib/rosette/core/resolvers/resolver.rb +115 -0
- data/lib/rosette/core/resolvers/serializer_id.rb +37 -0
- data/lib/rosette/core/snapshots/cached_head_snapshot_factory.rb +51 -0
- data/lib/rosette/core/snapshots/cached_snapshot_factory.rb +67 -0
- data/lib/rosette/core/snapshots/head_snapshot_factory.rb +58 -0
- data/lib/rosette/core/snapshots/repo_config_path_filter.rb +83 -0
- data/lib/rosette/core/snapshots/snapshot_factory.rb +184 -0
- data/lib/rosette/core/string_utils.rb +23 -0
- data/lib/rosette/core/translation_status.rb +81 -0
- data/lib/rosette/core/validators.rb +18 -0
- data/lib/rosette/core/validators/commit_validator.rb +62 -0
- data/lib/rosette/core/validators/commits_validator.rb +32 -0
- data/lib/rosette/core/validators/encoding_validator.rb +32 -0
- data/lib/rosette/core/validators/locale_validator.rb +37 -0
- data/lib/rosette/core/validators/repo_validator.rb +33 -0
- data/lib/rosette/core/validators/serializer_validator.rb +37 -0
- data/lib/rosette/core/validators/validator.rb +31 -0
- data/lib/rosette/core/version.rb +8 -0
- data/lib/rosette/data_stores.rb +11 -0
- data/lib/rosette/data_stores/errors.rb +26 -0
- data/lib/rosette/data_stores/phrase_status.rb +59 -0
- data/lib/rosette/integrations.rb +12 -0
- data/lib/rosette/integrations/errors.rb +15 -0
- data/lib/rosette/integrations/integratable.rb +58 -0
- data/lib/rosette/integrations/integration.rb +23 -0
- data/lib/rosette/preprocessors.rb +11 -0
- data/lib/rosette/preprocessors/errors.rb +14 -0
- data/lib/rosette/preprocessors/preprocessor.rb +48 -0
- data/lib/rosette/queuing.rb +14 -0
- data/lib/rosette/queuing/commits.rb +19 -0
- data/lib/rosette/queuing/commits/commit_conductor.rb +90 -0
- data/lib/rosette/queuing/commits/commit_job.rb +93 -0
- data/lib/rosette/queuing/commits/commits_queue_configurator.rb +60 -0
- data/lib/rosette/queuing/commits/extract_stage.rb +46 -0
- data/lib/rosette/queuing/commits/fetch_stage.rb +51 -0
- data/lib/rosette/queuing/commits/finalize_stage.rb +76 -0
- data/lib/rosette/queuing/commits/phrase_storage_granularity.rb +20 -0
- data/lib/rosette/queuing/commits/push_stage.rb +91 -0
- data/lib/rosette/queuing/commits/stage.rb +96 -0
- data/lib/rosette/queuing/job.rb +74 -0
- data/lib/rosette/queuing/queue.rb +28 -0
- data/lib/rosette/queuing/queue_configurator.rb +76 -0
- data/lib/rosette/queuing/worker.rb +30 -0
- data/lib/rosette/serializers.rb +10 -0
- data/lib/rosette/serializers/serializer.rb +98 -0
- data/lib/rosette/tms.rb +9 -0
- data/lib/rosette/tms/repository.rb +95 -0
- data/rosette-core.gemspec +24 -0
- data/spec/core/branch_utils_spec.rb +110 -0
- data/spec/core/commands/git/commit_command_spec.rb +60 -0
- data/spec/core/commands/git/diff_command_spec.rb +263 -0
- data/spec/core/commands/git/fetch_command_spec.rb +61 -0
- data/spec/core/commands/git/repo_snapshot_command_spec.rb +72 -0
- data/spec/core/commands/git/show_command_spec.rb +128 -0
- data/spec/core/commands/git/snapshot_command_spec.rb +86 -0
- data/spec/core/commands/git/status_command_spec.rb +154 -0
- data/spec/core/commands/queuing/enqueue_commit_command_spec.rb +34 -0
- data/spec/core/commands/queuing/requeue_commit_command_spec.rb +46 -0
- data/spec/core/commands/translations/export_command_spec.rb +113 -0
- data/spec/core/commands/translations/translation_lookup_command_spec.rb +58 -0
- data/spec/core/configurator_spec.rb +47 -0
- data/spec/core/error_reporters/buffered_error_reporter_spec.rb +61 -0
- data/spec/core/error_reporters/nil_error_reporter_spec.rb +16 -0
- data/spec/core/error_reporters/printing_error_reporter_spec.rb +60 -0
- data/spec/core/extractor/commit_log_status_spec.rb +216 -0
- data/spec/core/extractor/commit_processor_spec.rb +68 -0
- data/spec/core/extractor/extractor_config_spec.rb +47 -0
- data/spec/core/extractor/extractor_spec.rb +26 -0
- data/spec/core/extractor/locale_spec.rb +92 -0
- data/spec/core/extractor/phrase/phrase_index_policy_spec.rb +116 -0
- data/spec/core/extractor/phrase/phrase_to_hash_spec.rb +18 -0
- data/spec/core/extractor/repo_config_spec.rb +147 -0
- data/spec/core/extractor/translation/translation_to_hash_spec.rb +25 -0
- data/spec/core/git/diff_finder_spec.rb +74 -0
- data/spec/core/git/ref_spec.rb +118 -0
- data/spec/core/git/repo_spec.rb +216 -0
- data/spec/core/path_matcher_factory_spec.rb +139 -0
- data/spec/core/resolvers/extractor_id_spec.rb +47 -0
- data/spec/core/resolvers/integration_id_spec.rb +47 -0
- data/spec/core/resolvers/preprocessor_id_spec.rb +47 -0
- data/spec/core/resolvers/serializer_id_spec.rb +47 -0
- data/spec/core/snapshots/snapshot_factory_spec.rb +145 -0
- data/spec/core/string_utils_spec.rb +19 -0
- data/spec/core/translation_status_spec.rb +91 -0
- data/spec/core/validators/commit_validator_spec.rb +40 -0
- data/spec/core/validators/encoding_validator_spec.rb +30 -0
- data/spec/core/validators/locale_validator_spec.rb +31 -0
- data/spec/core/validators/repo_validator_spec.rb +30 -0
- data/spec/core/validators/serializer_validator_spec.rb +31 -0
- data/spec/integrations/integratable_spec.rb +58 -0
- data/spec/queuing/commits/commit_conductor_spec.rb +71 -0
- data/spec/queuing/commits/commit_job_spec.rb +87 -0
- data/spec/queuing/commits/extract_stage_spec.rb +68 -0
- data/spec/queuing/commits/fetch_stage_spec.rb +101 -0
- data/spec/queuing/commits/finalize_stage_spec.rb +88 -0
- data/spec/queuing/commits/push_stage_spec.rb +145 -0
- data/spec/queuing/commits/stage_spec.rb +80 -0
- data/spec/queuing/job_spec.rb +33 -0
- data/spec/queuing/queue_configurator_spec.rb +44 -0
- data/spec/spec_helper.rb +90 -0
- data/spec/test_helpers/fake_commit_stage.rb +17 -0
- metadata +257 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Rosette
|
4
|
+
module Core
|
5
|
+
|
6
|
+
# Raises errors instead of printing or logging them.
|
7
|
+
class RaisingErrorReporter < ErrorReporter
|
8
|
+
# Raises an error.
|
9
|
+
#
|
10
|
+
# @param [Exception] error The error to raise.
|
11
|
+
# @param [Hash] options A hash of associated options.
|
12
|
+
# @return [void]
|
13
|
+
def report_error(error, options = {})
|
14
|
+
raise error
|
15
|
+
end
|
16
|
+
|
17
|
+
# Does nothing.
|
18
|
+
#
|
19
|
+
# @param [Exception] error An error, but nothing is done with it.
|
20
|
+
# @param [Hash] options A hash of associated options.
|
21
|
+
# @return [void]
|
22
|
+
def report_warning(error, options = {})
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Rosette
|
4
|
+
module Core
|
5
|
+
|
6
|
+
# Represents a generic syntax error that probably occurred when attempting
|
7
|
+
# to parse a bit of source code or other well-defined text format.
|
8
|
+
#
|
9
|
+
# @!attribute [r] message
|
10
|
+
# @return [String] the error message.
|
11
|
+
# @!attribute [r] original_exception
|
12
|
+
# @return [Exception] the original exception, probably from a parser of
|
13
|
+
# some kind.
|
14
|
+
# @!attribute [r] language
|
15
|
+
# @return [Symbol] the language that the text the parser attempted to
|
16
|
+
# parse was in when this error was generated.
|
17
|
+
class SyntaxError < StandardError
|
18
|
+
attr_reader :message, :original_exception, :language
|
19
|
+
|
20
|
+
# Creates a new syntax error object.
|
21
|
+
#
|
22
|
+
# @param [String] msg The error message text.
|
23
|
+
# @param [Exception] original_exception The original error from the
|
24
|
+
# parser or some such.
|
25
|
+
# @param [Symbol] language The source code language.
|
26
|
+
def initialize(msg, original_exception, language)
|
27
|
+
super(msg)
|
28
|
+
@message = msg
|
29
|
+
@original_exception = original_exception
|
30
|
+
@language = language
|
31
|
+
end
|
32
|
+
|
33
|
+
# A string representation of this error which combines both the original
|
34
|
+
# message as well as the language.
|
35
|
+
#
|
36
|
+
# @return [String]
|
37
|
+
def message
|
38
|
+
"#{@message} (#{language})"
|
39
|
+
end
|
40
|
+
|
41
|
+
alias :to_s :message
|
42
|
+
end
|
43
|
+
|
44
|
+
# Represents a generic syntax error generated by one of Rosette's
|
45
|
+
# extractors. Since extractors parse source code and other
|
46
|
+
# well-defined text formats, there's always the possibility that these formats
|
47
|
+
# will contain syntax errors.
|
48
|
+
#
|
49
|
+
# @!attribute [r] original_exception
|
50
|
+
# @return [Exception] the original error from the parser or some such.
|
51
|
+
# @!attribute [r] language
|
52
|
+
# @return [Symbol] the source code language.
|
53
|
+
# @!attribute [r] file
|
54
|
+
# @return [String] the file that was being parsed when the error was
|
55
|
+
# generated.
|
56
|
+
# @!attribute [r] commit_id
|
57
|
+
# @return [String] the commit id that contained the file that was being
|
58
|
+
# parsed when the error was generated.
|
59
|
+
class ExtractionSyntaxError < StandardError
|
60
|
+
attr_reader :original_exception, :language, :file, :commit_id
|
61
|
+
|
62
|
+
# Creates a new syntax error object.
|
63
|
+
#
|
64
|
+
# @param [String] msg The error message text.
|
65
|
+
# @param [Exception] original_exception The original error from the
|
66
|
+
# parser or some such.
|
67
|
+
# @param [Symbol] language The source code language.
|
68
|
+
# @param [String] file The file that was being parsed when the error
|
69
|
+
# was generated.
|
70
|
+
# @param [String] commit_id The commit id that contained the file that
|
71
|
+
# was being parsed when the error was generated.
|
72
|
+
def initialize(msg, original_exception, language, file, commit_id)
|
73
|
+
super(msg)
|
74
|
+
@message = msg
|
75
|
+
@original_exception = original_exception
|
76
|
+
@language = language
|
77
|
+
@file = file
|
78
|
+
@commit_id = commit_id
|
79
|
+
end
|
80
|
+
|
81
|
+
# A string representation of this error which includes the original
|
82
|
+
# message, the source language, the file, and the commit id.
|
83
|
+
#
|
84
|
+
# @return [String]
|
85
|
+
def message
|
86
|
+
"#{@message}: #{original_exception.message} (#{language}) in #{file} at #{commit_id}"
|
87
|
+
end
|
88
|
+
|
89
|
+
alias :to_s :message
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Rosette
|
4
|
+
module Core
|
5
|
+
|
6
|
+
# Represents a commit log. Commit logs track the status of individual
|
7
|
+
# commits, what time the commit occurred, and how many phrases it contains.
|
8
|
+
#
|
9
|
+
# @!attribute [rw] repo_name
|
10
|
+
# @return [String] the name of the repo the commit was found in.
|
11
|
+
# @!attribute [rw] commit_id
|
12
|
+
# @return [String] the git commit id.
|
13
|
+
# @!attribute [rw] phrase_count
|
14
|
+
# @return [Fixnum] the number of phrases found in this commit.
|
15
|
+
# @!attribute [rw] status
|
16
|
+
# @return [String] the [PhraseStatus] of this commit.
|
17
|
+
# @!attribute [rw] commit_datetime
|
18
|
+
# @return [DateTime] the time this commit was made.
|
19
|
+
# @!attribute [rw] branch_name
|
20
|
+
# @return [String] the name of the branch that contains this commit.
|
21
|
+
class CommitLog
|
22
|
+
def initialize(repo_name, commit_id, phrase_count = nil, status = nil, commit_datetime = nil, branch_name = nil)
|
23
|
+
@repo_name = repo_name
|
24
|
+
@commit_id = commit_id
|
25
|
+
@phrase_count = phrase_count
|
26
|
+
@status = status
|
27
|
+
@commit_datetime = commit_datetime
|
28
|
+
@branch_name = branch_name
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'aasm'
|
4
|
+
|
5
|
+
module Rosette
|
6
|
+
module Core
|
7
|
+
|
8
|
+
# Provides a state machine for transitioning between the possible states of
|
9
|
+
# a commit log.
|
10
|
+
module CommitLogStatus
|
11
|
+
# aasm requires all states to be symbols
|
12
|
+
Rosette::DataStores::PhraseStatus.all.each do |status|
|
13
|
+
self.const_set(status, status.to_sym)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.included(base)
|
17
|
+
base.class_eval do
|
18
|
+
include AASM
|
19
|
+
|
20
|
+
aasm do
|
21
|
+
# define states from PhraseStatus constants
|
22
|
+
Rosette::DataStores::PhraseStatus.all.each do |status|
|
23
|
+
state status.to_sym
|
24
|
+
end
|
25
|
+
|
26
|
+
attribute_name :status
|
27
|
+
initial_state NOT_SEEN
|
28
|
+
|
29
|
+
event :fetch do
|
30
|
+
transitions from: NOT_SEEN, to: FETCHED
|
31
|
+
end
|
32
|
+
|
33
|
+
event :extract do
|
34
|
+
transitions from: FETCHED, to: EXTRACTED
|
35
|
+
end
|
36
|
+
|
37
|
+
event :push do
|
38
|
+
transitions from: [EXTRACTED, PUSHED], to: PUSHED
|
39
|
+
end
|
40
|
+
|
41
|
+
event :finalize do
|
42
|
+
transitions from: [EXTRACTED, PUSHED, FINALIZED], to: FINALIZED
|
43
|
+
end
|
44
|
+
|
45
|
+
# called when jgit can't find the commit
|
46
|
+
event :missing do
|
47
|
+
transitions(
|
48
|
+
from: Rosette::DataStores::PhraseStatus.statuses,
|
49
|
+
to: MISSING
|
50
|
+
)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
java_import 'org.eclipse.jgit.revwalk.RevWalk'
|
4
|
+
|
5
|
+
module Rosette
|
6
|
+
module Core
|
7
|
+
|
8
|
+
# Extracts phrases from a git commit. Should be thread-safe.
|
9
|
+
#
|
10
|
+
# @!attribute [r] config
|
11
|
+
# @return [Configurator] the Rosette config to use.
|
12
|
+
# @!attribute [r] error_reporter
|
13
|
+
# @return [ErrorReporter] the error reporter to report syntax
|
14
|
+
# errors, etc to.
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# processor = CommitProcessor.new(configuration)
|
18
|
+
# processor.process_each_phrase('my_repo', 'master') do |phrase|
|
19
|
+
# puts phrase.key
|
20
|
+
# end
|
21
|
+
class CommitProcessor
|
22
|
+
attr_reader :config, :error_reporter
|
23
|
+
|
24
|
+
# Creates a new processor.
|
25
|
+
#
|
26
|
+
# @param [Configurator] config The Rosette config to use.
|
27
|
+
# @param [ErrorReporter] error_reporter The error reporter to report
|
28
|
+
# syntax errors, etc to.
|
29
|
+
def initialize(config, error_reporter = NilErrorReporter.instance)
|
30
|
+
@config = config
|
31
|
+
@error_reporter = error_reporter
|
32
|
+
end
|
33
|
+
|
34
|
+
# Extracts translatable phrases from the given ref and yields them
|
35
|
+
# sequentially to the given block. If no block is given, this method
|
36
|
+
# returns an +Enumerator+.
|
37
|
+
#
|
38
|
+
# @param [String] repo_name The name of the repository to extract
|
39
|
+
# translatable phrases from. Must be configured in +config+.
|
40
|
+
# @param [String] commit_ref The git ref or commit id to extract
|
41
|
+
# translatable phrases from.
|
42
|
+
# @raise [Java::OrgEclipseJgitErrors::MissingObjectException]
|
43
|
+
# @return [void, Enumerator] either nothing if a block is given or
|
44
|
+
# an instance of +Enumerator+ if no block is given.
|
45
|
+
# @yield [phrase] a single extracted phrase.
|
46
|
+
# @yieldparam phrase [Phrase]
|
47
|
+
def process_each_phrase(repo_name, commit_ref)
|
48
|
+
if block_given?
|
49
|
+
repo_config = config.get_repo(repo_name)
|
50
|
+
rev_walk = RevWalk.new(repo_config.repo.jgit_repo)
|
51
|
+
diff_finder = DiffFinder.new(repo_config.repo.jgit_repo, rev_walk)
|
52
|
+
commit = repo_config.repo.get_rev_commit(commit_ref, rev_walk)
|
53
|
+
|
54
|
+
diff_finder.diff_with_parents(commit).each_pair do |_, diff_entries|
|
55
|
+
diff_entries.each do |diff_entry|
|
56
|
+
if diff_entry.getNewPath != '/dev/null'
|
57
|
+
process_diff_entry(diff_entry, repo_config, commit) do |phrase|
|
58
|
+
yield phrase
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
else
|
64
|
+
to_enum(__method__, repo_name, commit_ref)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
protected
|
69
|
+
|
70
|
+
def process_diff_entry(diff_entry, repo_config, commit)
|
71
|
+
repo_config.get_extractor_configs(diff_entry.getNewPath).each do |extractor_config|
|
72
|
+
source_code = read_object_from_entry(diff_entry, repo_config, extractor_config)
|
73
|
+
line_numbers_to_author = repo_config.repo.blame(diff_entry.getNewPath, commit.getId.name)
|
74
|
+
|
75
|
+
begin
|
76
|
+
extractor_config.extractor.extract_each_from(source_code) do |phrase, line_number|
|
77
|
+
phrase.file = diff_entry.getNewPath
|
78
|
+
phrase.commit_id = commit.getId.name
|
79
|
+
|
80
|
+
if extractor_config.extractor.supports_line_numbers?
|
81
|
+
if author_identity = line_numbers_to_author[line_number - 1]
|
82
|
+
phrase.author_name = author_identity.getName
|
83
|
+
phrase.author_email = author_identity.getEmailAddress
|
84
|
+
phrase.line_number = line_number
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
yield phrase
|
89
|
+
end
|
90
|
+
rescue SyntaxError => e
|
91
|
+
error_reporter.report_error(
|
92
|
+
ExtractionSyntaxError.new(
|
93
|
+
e.message, e.original_exception, e.language,
|
94
|
+
diff_entry.getNewPath, commit.getId.name
|
95
|
+
)
|
96
|
+
)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def read_object_from_entry(diff_entry, repo_config, extractor_config)
|
102
|
+
object_reader = repo_config.repo.jgit_repo.newObjectReader
|
103
|
+
bytes = object_reader.open(diff_entry.getNewId.toObjectId).getBytes
|
104
|
+
Java::JavaLang::String.new(bytes, extractor_config.encoding.to_s).to_s
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Rosette
|
4
|
+
module Core
|
5
|
+
|
6
|
+
# Base class for extractors that extract phrases from source code,
|
7
|
+
# eg. Ruby, JavaScript, HAML, etc.
|
8
|
+
#
|
9
|
+
# @!attribute [r] config
|
10
|
+
# @return [Configurator] the Rosette config to use.
|
11
|
+
class Extractor
|
12
|
+
attr_reader :config
|
13
|
+
|
14
|
+
# Creates a new extractor.
|
15
|
+
#
|
16
|
+
# @param [Configurator] config The Rosette config to use.
|
17
|
+
def initialize(config = nil)
|
18
|
+
@config = config
|
19
|
+
end
|
20
|
+
|
21
|
+
# Extracts each translatable phrase from the given source code.
|
22
|
+
# Derived classes must implement the +#each_function_call+ method
|
23
|
+
# for this to work.
|
24
|
+
#
|
25
|
+
# @param [String] source_code The source code to extract phrases
|
26
|
+
# from.
|
27
|
+
# @return [void, Enumerator] If passed a block, this method yields
|
28
|
+
# each consecutive phrase found in +source_code+. If no block is
|
29
|
+
# passed, it returns an +Enumerator+.
|
30
|
+
# @yield [phrase] a single extracted phrase.
|
31
|
+
# @yieldparam phrase [Phrase]
|
32
|
+
def extract_each_from(source_code)
|
33
|
+
if block_given?
|
34
|
+
each_function_call(source_code) do |node, line_number|
|
35
|
+
if valid_name?(node) && valid_args?(node)
|
36
|
+
yield make_phrase(get_key(node), get_meta_key(node)), line_number
|
37
|
+
end
|
38
|
+
end
|
39
|
+
else
|
40
|
+
to_enum(__method__, source_code)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
def each_function_call(source_code)
|
47
|
+
raise NotImplementedError, "#{__method__} must be implemented by derived classes."
|
48
|
+
end
|
49
|
+
|
50
|
+
def valid_name?(node)
|
51
|
+
raise NotImplementedError, "#{__method__} must be implemented by derived classes."
|
52
|
+
end
|
53
|
+
|
54
|
+
def valid_args?(node)
|
55
|
+
raise NotImplementedError, "#{__method__} must be implemented by derived classes."
|
56
|
+
end
|
57
|
+
|
58
|
+
def get_key(node)
|
59
|
+
raise NotImplementedError, "#{__method__} must be implemented by derived classes."
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_meta_key(node)
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
|
66
|
+
def make_phrase(key, meta_key = nil, file = nil)
|
67
|
+
Phrase.new(key, meta_key, file)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Rosette
|
4
|
+
module Core
|
5
|
+
|
6
|
+
# Configuration for an extractor.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# ex = ExtractorConfig.new(JsonExtractor::KeyValueExtractor)
|
10
|
+
# .set_encoding(Encoding::UTF_8)
|
11
|
+
# .set_conditions do |root|
|
12
|
+
# root.match_file_extension('.json').and(
|
13
|
+
# root.match_path('config/locales')
|
14
|
+
# )
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# @!attribute [r] extractor
|
18
|
+
# @return [Extractor] the extractor instance that will be used to
|
19
|
+
# extract phrases.
|
20
|
+
# @!attribute [r] encoding
|
21
|
+
# @return [String, Encoding] the encoding to expect the contents of
|
22
|
+
# source files to be in.
|
23
|
+
# @!attribute [r] root
|
24
|
+
# @return [PathMatcherFactory::Node] the root of the
|
25
|
+
# conditions tree. Only files that are matched by the conditions in
|
26
|
+
# this tree will have their phrases extracted.
|
27
|
+
class ExtractorConfig
|
28
|
+
attr_reader :extractor_id, :extractor, :encoding, :root
|
29
|
+
|
30
|
+
# Creates a new extractor configuration.
|
31
|
+
#
|
32
|
+
# @param [String] extractor_id The extractor id of +extractor_class+.
|
33
|
+
# @param [Class] extractor_class The extractor to use.
|
34
|
+
def initialize(extractor_id, extractor_class)
|
35
|
+
@extractor_id = extractor_id
|
36
|
+
@extractor = extractor_class.new(self)
|
37
|
+
@root = PathMatcherFactory.create_root
|
38
|
+
@encoding = Rosette::Core::DEFAULT_ENCODING
|
39
|
+
end
|
40
|
+
|
41
|
+
# Sets the encoding to expect the contents of source files to be in.
|
42
|
+
#
|
43
|
+
# @param [String, Encoding] new_encoding the encoding to use.
|
44
|
+
# @return [self]
|
45
|
+
def set_encoding(new_encoding)
|
46
|
+
@encoding = new_encoding
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
# Determines if the given path matches all the conditions in the
|
51
|
+
# conditions tree.
|
52
|
+
#
|
53
|
+
# @param [String] path The path to match.
|
54
|
+
# @return [Boolean] true if the path matches, false otherwise.
|
55
|
+
def matches?(path)
|
56
|
+
root.matches?(path)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Creates and yields a node that represents the root of a conditions
|
60
|
+
# tree. Callers should use the yielded root to build up a set of
|
61
|
+
# conditions that will be used to match paths in the repository.
|
62
|
+
# Matching paths will be processed by the extractor (i.e. their
|
63
|
+
# translatable phrases will be identified and stored).
|
64
|
+
#
|
65
|
+
# @return [self]
|
66
|
+
# @yield [root] the root of the conditions tree
|
67
|
+
# @yieldparam root [PathMatcherFactory::Node]
|
68
|
+
def set_conditions
|
69
|
+
@root = yield PathMatcherFactory.create_root
|
70
|
+
self
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|