tfs_graph 0.1.1 → 0.1.2

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/Gemfile +12 -4
  4. data/Rakefile +1 -0
  5. data/lib/tfs_graph.rb +1 -2
  6. data/lib/tfs_graph/abstract_store.rb +23 -0
  7. data/lib/tfs_graph/associators/branch_associator.rb +1 -1
  8. data/lib/tfs_graph/associators/changeset_tree_builder.rb +29 -0
  9. data/lib/tfs_graph/behaviors.rb +9 -0
  10. data/lib/tfs_graph/behaviors/neo4j_repository/branch.rb +39 -0
  11. data/lib/tfs_graph/behaviors/neo4j_repository/changeset.rb +12 -0
  12. data/lib/tfs_graph/behaviors/neo4j_repository/project.rb +89 -0
  13. data/lib/tfs_graph/behaviors/related_repository/branch.rb +26 -0
  14. data/lib/tfs_graph/behaviors/related_repository/changeset.rb +8 -0
  15. data/lib/tfs_graph/behaviors/related_repository/project.rb +48 -0
  16. data/lib/tfs_graph/branch.rb +84 -37
  17. data/lib/tfs_graph/branch/branch_archive_handler.rb +10 -6
  18. data/lib/tfs_graph/branch/branch_store.rb +13 -26
  19. data/lib/tfs_graph/changeset.rb +46 -25
  20. data/lib/tfs_graph/changeset/changeset_normalizer.rb +1 -0
  21. data/lib/tfs_graph/changeset/changeset_store.rb +13 -36
  22. data/lib/tfs_graph/changeset_merge.rb +20 -18
  23. data/lib/tfs_graph/changeset_merge/changeset_merge_store.rb +13 -10
  24. data/lib/tfs_graph/config.rb +12 -4
  25. data/lib/tfs_graph/entity.rb +34 -6
  26. data/lib/tfs_graph/extensions.rb +27 -0
  27. data/lib/tfs_graph/graph_populator.rb +9 -1
  28. data/lib/tfs_graph/persistable_entity.rb +60 -0
  29. data/lib/tfs_graph/populators/everything.rb +16 -4
  30. data/lib/tfs_graph/populators/for_archived_branch.rb +28 -0
  31. data/lib/tfs_graph/populators/for_branch.rb +35 -0
  32. data/lib/tfs_graph/populators/for_project.rb +22 -5
  33. data/lib/tfs_graph/populators/since_date.rb +21 -5
  34. data/lib/tfs_graph/populators/since_last.rb +22 -10
  35. data/lib/tfs_graph/populators/utilities.rb +4 -19
  36. data/lib/tfs_graph/project.rb +49 -13
  37. data/lib/tfs_graph/project/project_store.rb +13 -22
  38. data/lib/tfs_graph/repository.rb +78 -0
  39. data/lib/tfs_graph/repository/neo4j_repository.rb +97 -0
  40. data/lib/tfs_graph/repository/related_repository.rb +89 -0
  41. data/lib/tfs_graph/repository_registry.rb +60 -0
  42. data/lib/tfs_graph/server_registry.rb +45 -0
  43. data/lib/tfs_graph/store_helpers.rb +4 -5
  44. data/lib/tfs_graph/version.rb +1 -1
  45. data/schema.cypher +7 -0
  46. data/spec/branch_spec.rb +120 -0
  47. data/spec/neo4j_repository_integration_spec.rb +346 -0
  48. data/spec/persistable_entity_spec.rb +91 -0
  49. data/spec/project_spec.rb +29 -0
  50. data/spec/related_repository_integration_spec.rb +328 -0
  51. data/spec/repository_registry_spec.rb +48 -0
  52. data/spec/repository_spec.rb +73 -0
  53. data/spec/server_registery_spec.rb +36 -0
  54. data/spec/spec_helper.rb +12 -24
  55. data/tfs_graph.gemspec +3 -2
  56. metadata +67 -21
  57. data/lib/tfs_graph/associators/changeset_tree_creator.rb +0 -19
  58. data/spec/factories.rb +0 -20
@@ -1,3 +1,3 @@
1
1
  module TFSGraph
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -0,0 +1,7 @@
1
+ CREATE CONSTRAINT ON (p:project) ASSERT p.name IS UNIQUE;
2
+ CREATE CONSTRAINT ON (b:branch) ASSERT b.original_path IS UNIQUE;
3
+ CREATE CONSTRAINT ON (c:changeset) ASSERT c.id IS UNIQUE;
4
+ CREATE CONSTRAINT ON (r:root) ASSERT r.name IS UNIQUE;
5
+
6
+ CREATE INDEX ON :branch(path);
7
+ CREATE INDEX ON :branch(id);
@@ -0,0 +1,120 @@
1
+ require 'spec_helper'
2
+
3
+ require 'tfs_graph/branch'
4
+
5
+ describe TFSGraph::Branch do
6
+ Given(:repo) { flexmock("FakeRepository") }
7
+
8
+ context "estimates master and archive from name" do
9
+ When(:branch) { TFSGraph::Branch.new(repo, {
10
+ original_path: "$/Archived/Branch-A",
11
+ root: "",
12
+ path: "$/Branch-A",
13
+ name: "Branch-A"})
14
+ }
15
+ Then { branch.should be_archived }
16
+ And { branch.should be_master }
17
+ And { branch.named_type.should == :master }
18
+ And { branch.should_not be_branch }
19
+ end
20
+
21
+ context "updated state" do
22
+ When(:branch) { TFSGraph::Branch.new(repo, {
23
+ original_path: "$/Archived/Branch-A",
24
+ root: "",
25
+ path: "$/Branch-A",
26
+ name: "Branch-A"})
27
+ }
28
+
29
+ context "is updated" do
30
+ Given { repo.should_receive(:save).with(branch) }
31
+ When { branch.updated! }
32
+
33
+ context "can be set" do
34
+ When(:time) { branch.last_updated }
35
+ Then { expect(time).to be > Time.at(0).utc }
36
+ end
37
+
38
+ context "is updated" do
39
+ When(:updated) { branch.updated_since? 1.week.ago }
40
+ Then { updated.should be_true }
41
+ end
42
+
43
+ context "can compare with future" do
44
+ When(:updated) { branch.updated_since? 1.week.from_now }
45
+ Then { updated.should be_false }
46
+ end
47
+ end
48
+
49
+ context "is not updated" do
50
+ When(:updated) { branch.updated_since? 1.week.ago }
51
+ Then { updated.should be_false }
52
+ end
53
+ end
54
+
55
+ context "estimates release from name" do
56
+ When(:branch) { TFSGraph::Branch.new(repo, {
57
+ original_path: "$/Branch-R44-1234",
58
+ root: "$/Branch",
59
+ path: "$/Branch-R44-1234",
60
+ name: "Branch-R44-1234"})
61
+ }
62
+ Then { branch.should_not be_archived }
63
+ And { branch.should be_release }
64
+ And { branch.should_not be_rootless }
65
+ And { branch.named_type.should == :release }
66
+ And { branch.should be_branch }
67
+ end
68
+
69
+ context "estimates feature from name" do
70
+ When(:branch) { TFSGraph::Branch.new(repo, {
71
+ original_path: "$/Branch-My-Cool-Feature",
72
+ root: "$/Branch",
73
+ path: "$/Branch-My-Cool-Feature"})
74
+ }
75
+ Then { branch.should_not be_archived }
76
+ And { branch.should be_active }
77
+ And { branch.should be_feature }
78
+ And { branch.named_type.should == :feature }
79
+ end
80
+
81
+ context "hidden state" do
82
+ Given(:branch) { TFSGraph::Branch.new(repo, {
83
+ original_path: "$/Branch-My-Cool-Feature",
84
+ root: "$/Branch",
85
+ path: "$/Branch-My-Cool-Feature"})
86
+ }
87
+
88
+ context "is not initially set" do
89
+ Then { branch.should_not be_hidden }
90
+ And { branch.should be_active }
91
+ end
92
+
93
+ context "can be set" do
94
+ When { repo.should_receive(:save).with(branch) }
95
+ When { branch.hide! }
96
+ Then { branch.should be_hidden }
97
+ And { branch.should_not be_active }
98
+ end
99
+ end
100
+
101
+ context "archived state" do
102
+ Given(:branch) { TFSGraph::Branch.new(repo, {
103
+ original_path: "$/Branch-My-Cool-Feature",
104
+ root: "$/Branch",
105
+ path: "$/Branch-My-Cool-Feature"})
106
+ }
107
+
108
+ context "is not initially set" do
109
+ Then { branch.should_not be_archived }
110
+ And { branch.should be_active }
111
+ end
112
+
113
+ context "can be set" do
114
+ When { repo.should_receive(:save).with(branch) }
115
+ When { branch.archive! }
116
+ Then { branch.should be_archived }
117
+ And { branch.should_not be_active }
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,346 @@
1
+ require 'spec_helper'
2
+ require 'neo4j-core'
3
+
4
+ require 'tfs_graph/repository/neo4j_repository'
5
+ require 'tfs_graph/server_registry'
6
+ require 'tfs_graph/repository_registry'
7
+
8
+ require 'tfs_graph/associators/changeset_tree_builder'
9
+ require 'tfs_graph/changeset_merge'
10
+
11
+ # Integration testing between:
12
+ # - different repos
13
+ # - the registry
14
+ # - objects the repo returns
15
+
16
+ describe "Neo4j repo integration" do
17
+ before :all do
18
+ sesh = Neo4j::Session.open(:server_db, 'http://localhost:7474')
19
+ end
20
+
21
+ after :each do
22
+ TFSGraph::ServerRegistry.server.drop_all
23
+ end
24
+
25
+ Given(:register) { TFSGraph::RepositoryRegistry.register {|r|
26
+ r.type TFSGraph::Repository::Neo4jRepository
27
+ }}
28
+ Given(:project_repo) { register.project_repository }
29
+ Given { 3.times {|i| project_repo.create(name: "TestProject_#{i}") }}
30
+ Given { 2.times {|i| project_repo.create(name: "TestProject_#{i+7}", hidden: true) }}
31
+ Given(:foo) { project_repo.create(name: "TestProject_Foo") }
32
+
33
+ context "project lookups" do
34
+ context "can lookup all projects" do
35
+ When(:all) { project_repo.all }
36
+ Then { all.count.should == 5 }
37
+ And { all.all? {|p| p.is_a? TFSGraph::Project }.should be_true }
38
+ end
39
+
40
+ context "can lookup active projects only" do
41
+ When(:all) { project_repo.active }
42
+ Then { all.count.should == 3 }
43
+ end
44
+
45
+ context "can lookup by id" do
46
+ When(:project) { project_repo.find foo.id }
47
+ Then { project.should_not have_failed }
48
+ And { project.should == foo }
49
+ end
50
+
51
+ context "can lookup project by name" do
52
+ When(:project) { project_repo.find_by_name foo.name }
53
+ Then { project.name.should == foo.name }
54
+ end
55
+
56
+ context "throws not found error if id not found" do
57
+ When(:result) { project_repo.find 999 }
58
+ Then { result.should have_failed(TFSGraph::Repository::NotFound)}
59
+ end
60
+
61
+ context "throws not found error if name found" do
62
+ When(:result) { project_repo.find_by_name "FakeProject" }
63
+ Then { result.should have_failed(TFSGraph::Repository::NotFound)}
64
+ end
65
+ end
66
+
67
+ context "branches" do
68
+ Given(:branch_repo) { register.branch_repository }
69
+ context "basic branches" do
70
+ Given { 3.times do |i|
71
+ branch = branch_repo.create(path: "$/Root/Branch-#{i}", original_path: "$/Root/Branch-#{i}")
72
+ foo.add_branch(branch)
73
+ end
74
+ }
75
+
76
+ context "can find project for branch" do
77
+ Given(:branch) {
78
+ branch_repo.create(
79
+ path: "$/Root/Branch-Base",
80
+ original_path: "$/Root/Branch-Base",
81
+ project: "TestProject_Foo"
82
+ )
83
+ }
84
+ When(:project) { branch_repo.project_for_branch branch}
85
+ Then { project.should eq(foo) }
86
+ end
87
+
88
+ context "branch lookups through a project" do
89
+ When(:branches) { foo.branches }
90
+ Then { branches.size.should eq(3) }
91
+ And { branches.all? {|p| p.is_a? TFSGraph::Branch }.should be_true }
92
+ end
93
+
94
+ context "can get specific branch for a project by path" do
95
+ When(:branch) { branch_repo.find_in_project(foo, "$/Root/Branch-1") }
96
+ Then { branch.should_not be_nil }
97
+ And { branch.path.should eq("$/Root/Branch-1") }
98
+ end
99
+
100
+ context "project's branches" do
101
+ Given(:archived_branch) {
102
+ branch_repo.create(
103
+ path: "$/Root/Branch-Base",
104
+ original_path: "$/Root/Archived/Branch-Base",
105
+ project: "TestProject_Foo",
106
+ )
107
+ }
108
+ Given(:hidden_branch) {
109
+ branch_repo.create(
110
+ path: "$/Root/Branch-Base",
111
+ original_path: "$/Root/Branch-Boot",
112
+ project: "TestProject_Foo",
113
+ hidden: true
114
+ )
115
+ }
116
+ Given { foo.add_branch(archived_branch) }
117
+ Given { foo.add_branch(hidden_branch) }
118
+
119
+ context "active branches for a project" do
120
+ When(:active) { foo.active_branches }
121
+ Then { active.size.should eq(3) }
122
+ end
123
+
124
+ context "all non-hidden branches for a project" do
125
+ When(:visible) { foo.branches }
126
+ Then { visible.size.should eq(4) }
127
+ end
128
+
129
+ context "all with hidden" do
130
+ When(:all) { foo.branches_with_hidden }
131
+ Then { all.size.should eq(5) }
132
+ end
133
+
134
+ context "can get root branches" do
135
+ When(:roots) { project_repo.root_branches(foo) }
136
+ Then { roots.size.should eq(3) }
137
+ And { roots.all? {|r| r.master? }.should be_true }
138
+ end
139
+
140
+ context "can get root branches" do
141
+ When(:roots) { foo.root_branches }
142
+ Then { roots.size.should eq(3) }
143
+ end
144
+ end
145
+
146
+ context "changeset lookups" do
147
+ Given(:cs_repo) { register.changeset_repository }
148
+ Given(:branch) { foo.branches.first }
149
+ Given!(:changesets) {
150
+ 3.times.map do |i|
151
+ cs = cs_repo.create(comment: "Never gonna let you down.", id: "123#{i}".to_i, committer: "John Gray the #{i}th", created: i.days.ago.to_i)
152
+ branch.add_changeset(cs)
153
+ cs
154
+ end
155
+ }
156
+ Given!(:noise) {
157
+ # some extra noise
158
+ 3.times.map do |i|
159
+ cs = cs_repo.create(comment: "Never gonna give you up.", id: "323#{i}".to_i, commiter: "Jim Beam", created: i.days.ago)
160
+ foo.branches[1].add_changeset(cs)
161
+ cs
162
+ end
163
+ }
164
+ Given { TFSGraph::ChangesetTreeBuilder.to_tree branch, changesets }
165
+
166
+ context "paths are set" do
167
+ When(:cs) { branch.changesets }
168
+ Then { cs.map(&:branch_path).all? {|path| path == branch.path }.should be_true }
169
+ And { cs.all? {|b| b.is_a? TFSGraph::Changeset }.should be_true }
170
+ end
171
+
172
+ context "from a project" do
173
+ context "all" do
174
+ When(:activity) { foo.all_activity }
175
+ Then { activity.size.should == 6 }
176
+ And { expect(activity).to match_array(noise.concat(changesets)) }
177
+ end
178
+
179
+ context "all_activity_by_date" do
180
+ When(:activity) { foo.all_activity_by_date(0.5.days.ago) }
181
+ Then { activity.values.flatten.size.should == 2 }
182
+ And { expect(activity.values.flatten.map(&:id)).to match_array([3230, 1230]) }
183
+ end
184
+ end
185
+
186
+ context "from a branch" do
187
+ context "branch accessors" do
188
+ When(:authors) { branch.contributors }
189
+ Then { expect(authors.keys).to match_array(["John Gray the 0th", "John Gray the 1th", "John Gray the 2th"]) }
190
+ end
191
+
192
+ context "as a tree" do
193
+
194
+ context "branch can get it's root node" do
195
+ When(:root) { branch.root_changeset }
196
+ Then { root.should_not be_nil }
197
+ Then { root.id.should eq(1230) }
198
+ end
199
+
200
+ context "can get it's last node" do
201
+ When(:last) { branch.last_changeset }
202
+ Then { last.id.should eq(1232) }
203
+ end
204
+ end
205
+ end
206
+
207
+ context "within changesets" do
208
+ Given(:changeset) { changesets.first }
209
+
210
+ context "can walk the chain" do
211
+ Given(:results) { [] }
212
+ When {
213
+ child = changeset.next
214
+ loop do
215
+ results << child.id
216
+ child = child.next
217
+ end
218
+ }
219
+ Then { results.should match_array([1231, 1232])}
220
+ end
221
+
222
+ context "can get branch" do
223
+ When(:cs_branch) { changeset.branch }
224
+ Then { cs_branch.should eq(branch) }
225
+ end
226
+ end
227
+
228
+ context "with merges" do
229
+ Given(:merge_attrs) {[
230
+ {source_version: 1230, target_version: 3230},
231
+ {source_version: 1231, target_version: 3231},
232
+ {source_version: 1232, target_version: 3231}
233
+ ]}
234
+ Given { merge_attrs.each {|attrs| TFSGraph::ChangesetMerge.create attrs }}
235
+
236
+ context "parentage" do
237
+ Given(:child) { foo.branches[1] }
238
+ Given { child.root = branch.path; child.send :detect_type; child.save! }
239
+
240
+ Then { branch.should be_master }
241
+
242
+ context "related branches" do
243
+ When(:related) { child.related_branches }
244
+ Then { related.size.should eq(1) }
245
+ And { related.first.should == branch.id }
246
+ end
247
+
248
+ context "json reports related branches" do
249
+ When(:data) { JSON.parse child.to_json, symbolize_names: true }
250
+ Then { data[:related_branches].size.should eq(1) }
251
+ And { data[:related_branches].should match_array([branch.id]) }
252
+ end
253
+
254
+ context "get absolute root" do
255
+ When(:root) { child.absolute_root }
256
+ Then { root.should == branch }
257
+ end
258
+
259
+ context "ahead stats" do
260
+ When(:ahead) { child.ahead_of_master }
261
+ Then { ahead.should eq(1) }
262
+ end
263
+
264
+ context "behind stats" do
265
+ When(:behind) { child.behind_master }
266
+ Then { behind.should eq(0) }
267
+ end
268
+ end
269
+
270
+ context "merged changesets" do
271
+ When(:changeset) { cs_repo.find(1230) }
272
+ When(:merges) { changeset.merged }
273
+ Then { merges.size.should eq(1) }
274
+ And { merges.map(&:id).should match_array([3230]) }
275
+ end
276
+
277
+ context "merges changesets" do
278
+ When(:changeset) { cs_repo.find(3231) }
279
+ When(:merges) { changeset.merges }
280
+ Then { merges.size.should eq(2) }
281
+ And { merges.map(&:id).should match_array([1232, 1231]) }
282
+ end
283
+ end
284
+ end
285
+
286
+ end #####
287
+
288
+ shared_examples "branch type" do |type, name, root|
289
+ Given(:normal) {
290
+ branch_repo.create(
291
+ path: "$/Root/#{name}",
292
+ original_path: "$/Root/#{name}",
293
+ root: root,
294
+ name: name
295
+ )
296
+ }
297
+ Given(:archived) {
298
+ branch_repo.create(
299
+ path: "$/Root/#{name}",
300
+ original_path: "$/Root/Archived/#{name}",
301
+ root: root,
302
+ name: name
303
+ )
304
+ }
305
+ Given(:hidden) {
306
+ branch_repo.create(
307
+ path: "$/Root/#{name}",
308
+ original_path: "$/Root/#{name}",
309
+ root: root,
310
+ name: name,
311
+ hidden: true
312
+ )
313
+ }
314
+ Given { foo.add_branch(normal) }
315
+ Given { foo.add_branch(archived) }
316
+ Given { foo.add_branch(hidden) }
317
+
318
+ context "can find the #{type}s" do
319
+ When(:results) { foo.send "#{type}s" }
320
+ Then { results.size.should eq(1) }
321
+ end
322
+
323
+ context "can find the hidden #{type}s" do
324
+ When(:results) { foo.send "#{type}s_with_hidden" }
325
+ Then { results.size.should eq(2) }
326
+ end
327
+
328
+ context "can find the archived #{type}s" do
329
+ When(:results) { foo.send "archived_#{type}s" }
330
+ Then { results.size.should eq(1) }
331
+ end
332
+ end
333
+
334
+ context "can get the master branches" do
335
+ it_should_behave_like "branch type", "master", "Branch-Cool", ""
336
+ end
337
+
338
+ context "can get the release branches" do
339
+ it_should_behave_like "branch type", "release", "Branch-R22-1234", "Branch-Cool"
340
+ end
341
+
342
+ context "can get the feature" do
343
+ it_should_behave_like "branch type", "feature", "Branch-Base-Boot", "Branch-Cool"
344
+ end
345
+ end
346
+ end