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,25 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'spec_helper'
4
+
5
+ include Rosette::Core
6
+
7
+ describe TranslationToHash do
8
+ describe '#to_h' do
9
+ let(:phrase) do
10
+ TestPhrase.new('key', 'meta key', 'file', 'commit id')
11
+ end
12
+
13
+ it 'returns a hash of the appropriate attributes' do
14
+ TestTranslation.new(translation: 'translation', locale: 'es', phrase: phrase) do |t|
15
+ expect(t.to_h).to eq({
16
+ translation: 'translation', locale: 'es',
17
+ phrase: {
18
+ key: 'key', meta_key: 'meta key',
19
+ file: 'file', commit_id: 'commit id'
20
+ }
21
+ })
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,74 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'spec_helper'
4
+
5
+ include Rosette::Core
6
+
7
+ java_import 'org.eclipse.jgit.revwalk.RevWalk'
8
+ java_import 'org.eclipse.jgit.lib.ObjectId'
9
+
10
+ describe DiffFinder do
11
+ let(:repo_name) { 'double_commit' }
12
+ let(:fixture) { load_repo_fixture(repo_name) }
13
+ let(:repo) { Repo.from_path(fixture.repo_fixture.working_dir.join('.git').to_s) }
14
+ let(:rev_walk) { RevWalk.new(repo.jgit_repo) }
15
+ let(:diff_finder) { DiffFinder.new(repo.jgit_repo, rev_walk) }
16
+
17
+ let(:revs) do
18
+ fixture.each_commit.map do |fixture_commit|
19
+ rev_walk.parseCommit(ObjectId.fromString(fixture_commit.sha))
20
+ end
21
+ end
22
+
23
+ let(:first_file_contents) do
24
+ "I'm a little teapot\n" +
25
+ "The green albatross flitters in the moonlight\n"
26
+ end
27
+
28
+ let(:second_file_contents) do
29
+ "Chatanooga Choo Choo\n" +
30
+ "Diamonds are a girl's best friend.\n" +
31
+ "Cash for the merchandise; cash for the fancy goods.\n" +
32
+ "I'm in Spañish.\n"
33
+ end
34
+
35
+ describe '#diff' do
36
+ it 'returns the diff between the first two commits' do
37
+ commit_id = revs.first.getName
38
+
39
+ diff_finder.diff(revs.first, revs.last).tap do |diff|
40
+ expect(diff.size).to eq(1)
41
+ expect(diff[commit_id].first.getNewPath).to eq('second_file.txt')
42
+ expect(diff_finder.read_new_entry(diff[commit_id].first)).to(
43
+ eq(second_file_contents)
44
+ )
45
+ end
46
+ end
47
+ end
48
+
49
+ describe '#diff_with_parent' do
50
+ it 'returns the diff between the first two commits (just as a regular diff would do)' do
51
+ commit_id = revs.first.getName
52
+
53
+ diff_finder.diff_with_parents(revs.last).tap do |diff|
54
+ expect(diff.size).to eq(1)
55
+ expect(diff[revs.first.getName].first.getNewPath).to eq('second_file.txt')
56
+ expect(diff_finder.read_new_entry(diff[revs.first.getName].first)).to(
57
+ eq(second_file_contents)
58
+ )
59
+ end
60
+ end
61
+
62
+ it "returns the diff successfully if the rev doesn't have a parent" do
63
+ commit_id = revs.first.getName
64
+
65
+ diff_finder.diff_with_parents(revs.first).tap do |diff|
66
+ expect(diff.size).to eq(1)
67
+ expect(diff[commit_id].first.getNewPath).to eq('first_file.txt')
68
+ expect(diff_finder.read_new_entry(diff[commit_id].first)).to(
69
+ eq(first_file_contents)
70
+ )
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,118 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'spec_helper'
4
+
5
+ include Rosette::Core
6
+
7
+ describe Ref do
8
+ describe '.parse' do
9
+ it 'parses remotes' do
10
+ ref = Ref.parse('refs/remotes/origin/foobar')
11
+ expect(ref).to be_a(Remote)
12
+ end
13
+
14
+ it 'parses heads' do
15
+ ref = Ref.parse('refs/heads/foobar')
16
+ expect(ref).to be_a(Head)
17
+ end
18
+
19
+ it 'parses tags' do
20
+ ref = Ref.parse('refs/tags/foobar')
21
+ expect(ref).to be_a(Tag)
22
+ end
23
+ end
24
+ end
25
+
26
+ describe Remote do
27
+ describe '.create_from' do
28
+ it 'creates a new remote ref' do
29
+ remote = Remote.create_from(%w(remotes origin foobar))
30
+ expect(remote.remote).to eq('origin')
31
+ expect(remote.name).to eq('foobar')
32
+ end
33
+ end
34
+
35
+ context 'with a remote' do
36
+ let(:remote) { Remote.new('origin', 'foobar') }
37
+
38
+ describe '#type' do
39
+ it 'returns the correct type' do
40
+ expect(remote.type).to eq(:remote)
41
+ end
42
+ end
43
+
44
+ describe '#to_s' do
45
+ it 'constructs a string representation' do
46
+ expect(remote.to_s).to eq('refs/remotes/origin/foobar')
47
+ end
48
+ end
49
+
50
+ it 'responds correctly to query methods' do
51
+ expect(remote).to be_remote
52
+ expect(remote).to_not be_head
53
+ expect(remote).to_not be_tag
54
+ end
55
+ end
56
+ end
57
+
58
+ describe Head do
59
+ describe '.create_from' do
60
+ it 'creates a new head' do
61
+ head = Head.create_from(%w(heads foobar))
62
+ expect(head.name).to eq('foobar')
63
+ end
64
+ end
65
+
66
+ context 'with a head' do
67
+ let(:head) { Head.new('foobar') }
68
+
69
+ describe '#type' do
70
+ it 'returns the correct type' do
71
+ expect(head.type).to eq(:head)
72
+ end
73
+ end
74
+
75
+ describe '#to_s' do
76
+ it 'constructs a string representation' do
77
+ expect(head.to_s).to eq('refs/heads/foobar')
78
+ end
79
+ end
80
+
81
+ it 'responds correctly to query methods' do
82
+ expect(head).to be_head
83
+ expect(head).to_not be_remote
84
+ expect(head).to_not be_tag
85
+ end
86
+ end
87
+ end
88
+
89
+ describe Tag do
90
+ describe '.create_from' do
91
+ it 'creates a new tag' do
92
+ tag = Tag.create_from(%w(tags foobar))
93
+ expect(tag.name).to eq('foobar')
94
+ end
95
+ end
96
+
97
+ context 'with a tag' do
98
+ let(:tag) { Tag.new('foobar') }
99
+
100
+ describe '#type' do
101
+ it 'returns the correct type' do
102
+ expect(tag.type).to eq(:tag)
103
+ end
104
+ end
105
+
106
+ describe '#to_s' do
107
+ it 'constructs a string representation' do
108
+ expect(tag.to_s).to eq('refs/tags/foobar')
109
+ end
110
+ end
111
+
112
+ it 'responds correctly to query methods' do
113
+ expect(tag).to be_tag
114
+ expect(tag).to_not be_head
115
+ expect(tag).to_not be_remote
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,216 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'spec_helper'
4
+
5
+ include Rosette::Core
6
+
7
+ java_import 'org.eclipse.jgit.lib.ObjectId'
8
+
9
+ describe Repo do
10
+ let(:repo_class) { Repo }
11
+
12
+ describe 'self.from_path' do
13
+ it 'returns a new repo at the given path' do
14
+ tmp_repo = TmpRepo.new
15
+ repo = repo_class.from_path(tmp_repo.working_dir.join('.git').to_s)
16
+ expect(repo.path).to eq(tmp_repo.working_dir.to_s)
17
+ tmp_repo.unlink
18
+ end
19
+ end
20
+
21
+ context 'with the double commit fixture' do
22
+ let(:repo_name) { 'double_commit' }
23
+ let(:fixture) { load_repo_fixture(repo_name) }
24
+ let(:repo) { repo_class.from_path(fixture.working_dir.join('.git').to_s) }
25
+ let(:commits) do
26
+ fixture.git('rev-list --all').split("\n").map do |sha|
27
+ repo.get_rev_commit(sha)
28
+ end.reverse
29
+ end
30
+
31
+ describe '#get_rev_commit' do
32
+ it 'returns a rev commit for a symbolic ref' do
33
+ commit = repo.get_rev_commit('HEAD')
34
+ expect(commit.getName).to eq(commits.last.getName)
35
+ end
36
+
37
+ it 'returns a rev commit for a sha' do
38
+ commit = repo.get_rev_commit(commits.last.getName)
39
+ expect(commit.getName).to eq(commits.last.getName)
40
+ end
41
+
42
+ it "falls back to remotes if the branch hasn't been checked out locally" do
43
+ branch_name = 'my_remote_branch'
44
+
45
+ remote_repo = TmpRepo.new.tap do |r|
46
+ r.create_branch(branch_name)
47
+ r.create_file('foo.txt') { |f| f.write('foo') }
48
+ r.add_all
49
+ r.commit('Initial commit')
50
+ end
51
+
52
+ fixture.repo.git("remote add origin file://#{remote_repo.working_dir}")
53
+ fixture.repo.git('fetch')
54
+
55
+ remote_commit_id = remote_repo.git('rev-parse HEAD').strip
56
+ commit = repo.get_rev_commit(branch_name)
57
+ expect(commit.getName).to eq(remote_commit_id)
58
+ end
59
+ end
60
+
61
+ describe '#diff' do
62
+ it 'returns the diff when a symbolic ref is involved' do
63
+ commit_id = commits.first.getName
64
+ repo.diff(commit_id, 'HEAD').tap do |diff|
65
+ expect(diff.size).to eq(1)
66
+ expect(diff[commit_id].first.getNewPath).to eq('second_file.txt')
67
+ end
68
+ end
69
+
70
+ it 'returns the diff between two shas' do
71
+ first_commit_id = commits.first.getName
72
+ second_commit_id = commits.last.getName
73
+ repo.diff(first_commit_id, second_commit_id).tap do |diff|
74
+ expect(diff.size).to eq(1)
75
+ expect(diff[first_commit_id].first.getNewPath).to eq('second_file.txt')
76
+ end
77
+ end
78
+ end
79
+
80
+ describe '#ref_diff_with_parents' do
81
+ it 'returns the correct diff' do
82
+ commit_id = commits.first.getName
83
+ repo.ref_diff_with_parents('HEAD').tap do |diff|
84
+ expect(diff.size).to eq(1)
85
+ expect(diff[commit_id].first.getNewPath).to eq('second_file.txt')
86
+ end
87
+ end
88
+ end
89
+
90
+ describe '#rev_diff_with_parents' do
91
+ it 'returns the correct diff' do
92
+ commit_id = commits.first.getName
93
+ repo.rev_diff_with_parents(repo.get_rev_commit('HEAD')).tap do |diff|
94
+ expect(diff.size).to eq(1)
95
+ expect(diff[commit_id].first.getNewPath).to eq('second_file.txt')
96
+ end
97
+ end
98
+ end
99
+
100
+ describe '#path' do
101
+ it 'returns the current working directory' do
102
+ expect(repo.path).to eq(fixture.working_dir.to_s)
103
+ end
104
+ end
105
+
106
+ describe '#read_object_bytes' do
107
+ it 'returns a byte array containing the object of the given id' do
108
+ object_id = ObjectId.fromString(fixture.git('hash-object first_file.txt').strip)
109
+ actual_bytes = repo.read_object_bytes(object_id)
110
+ expected_bytes = "I'm a little teapot\nThe green albatross flitters in the moonlight\n".bytes
111
+
112
+ expected_bytes.each_with_index do |expected_byte, index|
113
+ expect(actual_bytes[index]).to eq(expected_byte)
114
+ end
115
+ end
116
+ end
117
+
118
+ describe '#each_commit' do
119
+ it 'yields each commit or returns an enumerator' do
120
+ repo.each_commit.tap do |commit_enum|
121
+ expect(commit_enum).to be_a(Enumerator)
122
+ expect(commit_enum.map(&:getName)).to eq(commits.map(&:getName))
123
+ end
124
+ end
125
+ end
126
+
127
+ describe '#commit_count' do
128
+ it 'returns the total number of commits in the repo' do
129
+ expect(repo.commit_count).to eq(2)
130
+ end
131
+ end
132
+ end
133
+
134
+ context 'with the four commits fixture' do
135
+ let(:repo_name) { 'four_commits' }
136
+ let(:fixture) { load_repo_fixture(repo_name) }
137
+ let(:repo) { repo_class.from_path(fixture.working_dir.join('.git').to_s) }
138
+ let(:commits) do
139
+ fixture.git('rev-list --all').split("\n").map do |sha|
140
+ repo.get_rev_commit(sha)
141
+ end.reverse
142
+ end
143
+
144
+ describe '#each_commit_in_range' do
145
+ it 'yields only the commits in the given range' do
146
+ commit_args = [commits[2].getId.name, commits[0].getId.name]
147
+
148
+ found_commits = repo.each_commit_in_range(*commit_args).map do |c|
149
+ c.getId.name
150
+ end
151
+
152
+ expect(found_commits).to(
153
+ eq(commits[0..2].map { |c| c.getId.name }.reverse)
154
+ )
155
+ end
156
+ end
157
+ end
158
+
159
+ context 'with a merge commit fixture' do
160
+ let(:repo_name) { 'merge_commit' }
161
+ let(:fixture) { load_repo_fixture(repo_name) }
162
+ let(:repo) { repo_class.from_path(fixture.working_dir.join('.git').to_s) }
163
+ let(:commits) do
164
+ fixture.git('rev-list --all').split("\n").map do |sha|
165
+ repo.get_rev_commit(sha)
166
+ end
167
+ end
168
+
169
+ describe '#parents_of' do
170
+ it 'returns a single commit for a commit with a single parent' do
171
+ repo.parents_of(commits[1]).tap do |parents|
172
+ expect(parents.size).to eq(1)
173
+ expect(parents.first.getName).to eq(commits.last.getName)
174
+ end
175
+ end
176
+
177
+ it 'returns multiple parents when given a merge commit' do
178
+ repo.parents_of(commits.first).tap do |parents|
179
+ expect(parents.size).to eq(2)
180
+ parent_shas = parents.map(&:getName)
181
+ expect(parent_shas).to include(commits.last.getName)
182
+ expect(parent_shas).to include(commits[1].getName)
183
+ end
184
+ end
185
+ end
186
+
187
+ describe '#parent_ids_of' do
188
+ it 'returns a single sha for a commit with a single parent' do
189
+ repo.parent_ids_of(commits[1]).tap do |parent_ids|
190
+ expect(parent_ids).to eq([commits.last.getName])
191
+ end
192
+ end
193
+
194
+ it 'returns multiple parent shas when given a merge commit' do
195
+ repo.parent_ids_of(commits.first).tap do |parent_ids|
196
+ expect(parent_ids).to eq(commits[1..-1].reverse.map(&:getName))
197
+ end
198
+ end
199
+ end
200
+
201
+ describe '#commit_count' do
202
+ it 'returns the total number of commits in the repo' do
203
+ expect(repo.commit_count).to eq(3)
204
+ end
205
+ end
206
+
207
+ describe '#refs_containing' do
208
+ it 'returns the refs that contain the given commit' do
209
+ refs = repo.refs_containing(commits.last.getId.name)
210
+ expect(refs.map(&:getName)).to eq([
211
+ "HEAD", "refs/heads/master", "refs/heads/mybranch"
212
+ ])
213
+ end
214
+ end
215
+ end
216
+ end
@@ -0,0 +1,139 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'spec_helper'
4
+
5
+ include Rosette::Core
6
+
7
+ describe PathMatcherFactory do
8
+ let(:factory) { PathMatcherFactory }
9
+
10
+ describe '#create_root' do
11
+ it 'returns an empty, generic node' do
12
+ # instance_of returns false for subclasses of Node
13
+ expect(factory.create_root).to be_instance_of(factory::Node)
14
+ end
15
+ end
16
+
17
+ let(:root) { factory.create_root }
18
+
19
+ describe 'operators' do
20
+ it 'supports the and binary operator' do
21
+ node = root.match_path('foo/bar').and(root.match_path('foo/baz'))
22
+ expect(node).to be_a(factory::BinaryNode)
23
+ expect(node).to be_a(factory::AndNode)
24
+
25
+ node.left.tap do |left|
26
+ expect(left).to be_a(factory::PathNode)
27
+ expect(left.path).to eq('foo/bar')
28
+ end
29
+
30
+ node.right.tap do |right|
31
+ expect(right).to be_a(factory::PathNode)
32
+ expect(right.path).to eq('foo/baz')
33
+ end
34
+ end
35
+
36
+ it 'supports the or binary operator' do
37
+ node = root.match_path('foo/bar').or(root.match_path('foo/baz'))
38
+ expect(node).to be_a(factory::BinaryNode)
39
+ expect(node).to be_a(factory::OrNode)
40
+
41
+ node.left.tap do |left|
42
+ expect(left).to be_a(factory::PathNode)
43
+ expect(left.path).to eq('foo/bar')
44
+ end
45
+
46
+ node.right.tap do |right|
47
+ expect(right).to be_a(factory::PathNode)
48
+ expect(right.path).to eq('foo/baz')
49
+ end
50
+ end
51
+
52
+ it 'supports the unary not operator' do
53
+ node = root.match_path('foo/bar').not
54
+ expect(node).to be_a(factory::UnaryNode)
55
+ expect(node).to be_a(factory::NotNode)
56
+
57
+ node.child.tap do |child|
58
+ expect(child).to be_a(factory::PathNode)
59
+ expect(child.path).to eq('foo/bar')
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ context 'nodes' do
66
+ let(:factory) { PathMatcherFactory }
67
+ let(:root) { factory.create_root }
68
+
69
+ describe PathMatcherFactory::AndNode do
70
+ describe '#matches?' do
71
+ it 'returns true if both paths match, false otherwise' do
72
+ node = root.match_path('foo/bar').and(root.match_path('foo/bar/baz'))
73
+ expect(node).to be_a(factory::AndNode)
74
+ expect(node.matches?('foo/bar/baz/goo')).to be_truthy
75
+ expect(node.matches?('foo/bar')).to be_falsy
76
+ end
77
+ end
78
+ end
79
+
80
+ describe PathMatcherFactory::OrNode do
81
+ describe '#matches?' do
82
+ it 'returns true if either path matches, false otherwise' do
83
+ node = root.match_path('foo').or(root.match_path('goo'))
84
+ expect(node).to be_a(factory::OrNode)
85
+ expect(node.matches?('foo')).to be_truthy
86
+ expect(node.matches?('foo/bar')).to be_truthy
87
+ expect(node.matches?('goo')).to be_truthy
88
+ expect(node.matches?('goo/boo')).to be_truthy
89
+ expect(node.matches?('ya/ya')).to be_falsy
90
+ end
91
+ end
92
+ end
93
+
94
+ describe PathMatcherFactory::NotNode do
95
+ describe '#matches?' do
96
+ it "returns true if the path doesn't match, false otherwise" do
97
+ node = root.match_path('foo').not
98
+ expect(node).to be_a(factory::NotNode)
99
+ expect(node.matches?('bar')).to be_truthy
100
+ expect(node.matches?('foo')).to be_falsy
101
+ expect(node.matches?('foo/bar')).to be_falsy
102
+ end
103
+ end
104
+ end
105
+
106
+ describe PathMatcherFactory::FileExtensionNode do
107
+ describe '#matches?' do
108
+ it 'returns true if the file extension matches, false otherwise' do
109
+ node = root.match_file_extension('.rb')
110
+ expect(node).to be_a(factory::FileExtensionNode)
111
+ expect(node.matches?('file.rb')).to be_truthy
112
+ expect(node.matches?('file.txt')).to be_falsy
113
+ end
114
+ end
115
+ end
116
+
117
+ describe PathMatcherFactory::PathNode do
118
+ describe '#matches?' do
119
+ it 'returns true if the path matches, false otherwise' do
120
+ node = root.match_path('foo/bar')
121
+ expect(node).to be_a(factory::PathNode)
122
+ expect(node.matches?('foo/bar')).to be_truthy
123
+ expect(node.matches?('foo/bar/baz')).to be_truthy
124
+ expect(node.matches?('foo')).to be_falsy
125
+ end
126
+ end
127
+ end
128
+
129
+ describe PathMatcherFactory::RegexNode do
130
+ describe '#matches?' do
131
+ it 'returns true if the path matches a regex, false otherwise' do
132
+ node = root.match_regex(/[a-z]{2}\.rb/)
133
+ expect(node).to be_a(factory::RegexNode)
134
+ expect(node.matches?('fi.rb')).to be_truthy
135
+ expect(node.matches?('fi.txt')).to be_falsy
136
+ end
137
+ end
138
+ end
139
+ end