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
@@ -0,0 +1,27 @@
1
+ require 'active_support/inflector'
2
+ require 'active_support/concern'
3
+
4
+ module TFSGraph
5
+ module Extensions
6
+ extend ActiveSupport::Concern
7
+
8
+ module ClassMethods
9
+ def base_class_name
10
+ name.demodulize
11
+ end
12
+ end
13
+
14
+ def base_class_name
15
+ self.class.base_class_name
16
+ end
17
+
18
+ private
19
+ def add_behavior(repo, additions)
20
+ repo.extend additions
21
+ end
22
+
23
+ def constantize(string)
24
+ string.constantize
25
+ end
26
+ end
27
+ end
@@ -3,7 +3,7 @@ require 'tfs_graph/branch/branch_store'
3
3
  require 'tfs_graph/changeset/changeset_store'
4
4
  require 'tfs_graph/changeset_merge/changeset_merge_store'
5
5
 
6
- require 'tfs_graph/associators/changeset_tree_creator'
6
+ require 'tfs_graph/associators/changeset_tree_builder'
7
7
  require 'tfs_graph/associators/branch_associator'
8
8
  require 'tfs_graph/branch/branch_archive_handler'
9
9
 
@@ -30,6 +30,14 @@ module TFSGraph
30
30
  def populate_all_from_time(time)
31
31
  populate_graph(Populators::SinceDate, time)
32
32
  end
33
+
34
+ def update_project(project)
35
+ populate_graph(Populators::ForProject, project)
36
+ end
37
+
38
+ def update_branch(project, branch)
39
+ populate_graph(Populators::ForBranch, project, branch)
40
+ end
33
41
  end
34
42
  end
35
43
  end
@@ -0,0 +1,60 @@
1
+ require 'tfs_graph/entity'
2
+ require 'tfs_graph/extensions'
3
+
4
+ module TFSGraph
5
+ class PersistableEntity < Entity
6
+ include Comparable
7
+ include Extensions
8
+
9
+ NotPersisted = Class.new(RuntimeError)
10
+
11
+ attr_accessor :db_object, :id
12
+
13
+ def self.repository
14
+ TFSGraph::RepositoryRegistry.instance.send "#{base_class_name.downcase}_repository"
15
+ end
16
+
17
+ def initialize(repo, args)
18
+ @repo = repo
19
+ super args
20
+ end
21
+
22
+ def persisted?
23
+ !db_object.nil?
24
+ end
25
+
26
+ def save!
27
+ @repo.save(self)
28
+ end
29
+
30
+ def delete!
31
+ @repo.delete(self)
32
+
33
+ @db_object = nil
34
+ @id = nil
35
+ end
36
+
37
+ def persist(id, db_object)
38
+ @id ||= id
39
+ @db_object = db_object
40
+
41
+ self
42
+ end
43
+
44
+ def db_object
45
+ return nil unless id
46
+
47
+ begin
48
+ @db_object ||= @repo.find_native(id)
49
+ rescue Repository::NotFound
50
+ end
51
+ end
52
+
53
+ def to_hash
54
+ hash = super
55
+ hash[:id] = id
56
+
57
+ hash
58
+ end
59
+ end
60
+ end
@@ -6,13 +6,25 @@ module TFSGraph
6
6
  def populate
7
7
  clean
8
8
 
9
- collect_projects.map do |project|
10
- branches = collect_branches(project)
11
- branches.map {|branch| collect_changesets(branch) }
9
+ projects = ProjectStore.fetch_and_cache
12
10
 
13
- branches.each {|branch| collect_merges(branch) }
11
+ projects.each do |project|
12
+ branches = BranchStore.new(project).fetch_and_cache
13
+
14
+ changesets = branches.select(&:active?).map do |branch|
15
+ changesets = ChangesetStore.new(branch).fetch_and_cache
16
+ ChangesetTreeBuilder.to_tree(branch, changesets)
17
+
18
+ branch.updated!
19
+ changesets
20
+ end
21
+
22
+ ChangesetTreeBuilder.set_branch_merges(changesets)
23
+
24
+ project.updated!
14
25
  end
15
26
 
27
+ BranchArchiveHandler.hide_moved_archives_for_project(projects)
16
28
  finalize
17
29
  end
18
30
  end
@@ -0,0 +1,28 @@
1
+ module TFSGraph
2
+ module Populators
3
+
4
+ # incremental updates for a branch and its changesets
5
+ # does not update merges. have to do that once all changesets
6
+ # for a project are fetched
7
+ class ForArchivedBranch
8
+ include Utilities
9
+
10
+ def initialize(project, branch)
11
+ @project = project
12
+ @branch = branch
13
+
14
+ @changeset_store = ChangesetStore.new(branch)
15
+ end
16
+
17
+ def populate
18
+ return @branch.changesets unless @branch.changesets.empty?
19
+
20
+ all_changesets = @changeset_store.fetch_and_cache
21
+ ChangesetTreeBuilder.to_tree(@branch, all_changesets.sort)
22
+
23
+ @branch.updated!
24
+ all_changesets
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,35 @@
1
+ module TFSGraph
2
+ module Populators
3
+
4
+ # incremental updates for a branch and its changesets
5
+ # does not update merges. have to do that once all changesets
6
+ # for a project are fetched
7
+ class ForBranch
8
+ include Utilities
9
+
10
+ def initialize(project, branch)
11
+ @project = project
12
+ @branch = branch
13
+
14
+ @changeset_store = ChangesetStore.new(branch)
15
+ end
16
+
17
+ def populate
18
+ populate_since(@branch.last_updated.iso8601)
19
+ end
20
+
21
+ def populate_since(time)
22
+ new_changesets = @changeset_store.fetch_since_date(time)
23
+ @changeset_store.cache_all new_changesets
24
+
25
+ # skip rebuilding tree or marking as updated if no new were found
26
+ return new_changesets if new_changesets.empty?
27
+
28
+ ChangesetTreeBuilder.to_tree(@branch, @branch.changesets.sort)
29
+
30
+ @branch.updated!
31
+ new_changesets
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,18 +1,35 @@
1
+ require 'tfs_graph/populators/for_branch'
2
+
1
3
  module TFSGraph
2
4
  module Populators
5
+
6
+ #incremental updates for a project, its branches, changesets and merges
3
7
  class ForProject
4
8
  include Utilities
5
9
 
6
- def initialize(project)
10
+ def initialize(project, since=Time.at(0).utc)
7
11
  @project = project
12
+ @branch_store = BranchStore.new(@project)
8
13
  end
9
14
 
10
15
  def populate
11
- branches = collect_branches(@project)
12
- branches.map {|branch| collect_changesets(branch) }
16
+ new_branches = @branch_store.fetch_since_last_update
17
+ @branch_store.cache_all(new_branches)
18
+
19
+ active_branches = @project.active_branches
20
+
21
+ changesets = active_branches.map do |branch|
22
+ ForBranch.new(@project, branch).populate
23
+ branch.changesets
24
+ end
25
+
26
+ # Add merges
27
+ active_branches.each {|branch| ChangesetMergeStore.new(branch).fetch_and_cache }
28
+ ChangesetTreeBuilder.set_branch_merges(changesets.flatten)
13
29
 
14
- branches.each {|branch| collect_merges(branch) }
30
+ BranchArchiveHandler.hide_moved_archives_for_project(@project)
31
+ @project.updated!
15
32
  end
16
33
  end
17
34
  end
18
- end
35
+ end
@@ -7,16 +7,32 @@ module TFSGraph
7
7
  @since = since
8
8
  end
9
9
 
10
+ # could use the ForProject populator, except that we allow
11
+ # specification of a date rather than using last updated.
12
+ # also dumps all existing data
10
13
  def populate
11
14
  clean
12
15
 
13
- collect_projects.map do |project|
14
- branches = collect_branches(project)
15
- branches.map do |branch|
16
- collect_changesets(branch, :cache_since_date, @since)
16
+ projects = ProjectStore.fetch_and_cache
17
+
18
+ projects.each do |project|
19
+ ForProject.new(project).populate
20
+ branches = BranchStore.new(project).fetch_and_cache
21
+
22
+ changesets = branches.select(&:active?).map do |branch|
23
+ changesets = ChangesetStore.new(branch).fetch_since_date @since
24
+ ChangesetTreeBuilder.to_tree(branch, changesets)
25
+
26
+ branch.updated!
27
+ changesets
17
28
  end
18
29
 
19
- branches.each {|branch| collect_merges(branch) }
30
+ # setup merges
31
+ branches.each {|branch| ChangesetMergeStore.new(branch).fetch_and_cache }
32
+ ChangesetTreeBuilder.set_branch_merges(changesets)
33
+
34
+ BranchArchiveHandler.hide_moved_archives_for_project(@project)
35
+ project.updated!
20
36
  end
21
37
 
22
38
  finalize
@@ -4,23 +4,35 @@ module TFSGraph
4
4
  include Utilities
5
5
 
6
6
  def populate
7
- ProjectStore.all_cached.map do |project|
8
- new_changesets = project.active_branches.map {|branch| collect_changesets branch, :cache_since_last_update}
9
- new_branches = BranchStore.new(project).cache_since_last_update
7
+ projects = ProjectStore.new.fetch_all
8
+ existing_projects = RepositoryRegistry.project_repository.all
10
9
 
11
- new_changesets.concat new_branches.map {|branch| collect_changesets branch }
10
+ names = existing_projects.map(&:name)
11
+ new_project_data = projects.reject {|project| names.include? project[:name] }
12
+ new_projects = ProjectStore.cache_all(new_project_data)
12
13
 
13
- # recache and reassociate all merges for all branches.
14
- # should not lead to dupes thanks to Related
15
- new_branches.concat(project.branches).each do |branch|
16
- collect_merges(branch)
17
- BranchAssociator.associate(branch.changesets)
14
+ existing_projects.concat(new_projects).each do |project|
15
+ ForProject.new(project).populate
16
+ branches = BranchStore.new(project).fetch_and_cache
17
+
18
+ changesets = branches.select(&:active?).map do |branch|
19
+ changesets = ChangesetStore.new(branch).fetch_since_date @since
20
+ ChangesetTreeBuilder.to_tree(branch, changesets)
21
+
22
+ branch.updated!
23
+ changesets
18
24
  end
25
+
26
+ # setup merges
27
+ branches.each {|branch| ChangesetMergeStore.new(branch).fetch_and_cache }
28
+ ChangesetTreeBuilder.set_branch_merges(changesets)
29
+
30
+ BranchArchiveHandler.hide_moved_archives_for_project(@project)
31
+ project.updated!
19
32
  end
20
33
 
21
34
  finalize
22
35
  end
23
-
24
36
  end
25
37
  end
26
38
  end
@@ -8,30 +8,15 @@ module TFSGraph
8
8
  end
9
9
 
10
10
  def finalize
11
- BranchArchiveHandler.hide_all_archives
12
11
  mark_as_updated
13
12
  end
14
13
 
15
- def collect_projects
16
- ProjectStore.cache
14
+ def find_project(name)
15
+ TFSGraph::RepositoryRegistry.project_repository.find_by_name name
17
16
  end
18
17
 
19
- def collect_branches(project)
20
- BranchStore.new(project).cache_all
21
- end
22
-
23
- def collect_changesets(branch, method=:cache_all, *args)
24
- changesets = ChangesetStore.new(branch).send(method, *args)
25
- generate_branch_tree(branch)
26
- changesets.compact
27
- end
28
-
29
- def generate_branch_tree(branch)
30
- ChangesetTreeCreator.to_tree branch
31
- end
32
-
33
- def collect_merges(branch)
34
- ChangesetMergeStore.new(branch).cache
18
+ def find_branch(path)
19
+ TFSGraph::RepositoryRegistry.branch_repository.find_by_path path
35
20
  end
36
21
  end
37
22
  end
@@ -1,33 +1,57 @@
1
- require 'tfs_graph/entity'
1
+ require 'tfs_graph/persistable_entity'
2
2
 
3
3
  module TFSGraph
4
- class Project < Entity
5
- extend Comparable
4
+ class Project < PersistableEntity
6
5
  SCHEMA = {
7
- name: {key: "Name"}
6
+ name: {key: "Name"},
7
+ last_updated: {type: Time, default: Time.at(0).utc},
8
+ hidden: {default: false, type: String}
8
9
  }
9
10
 
10
11
  act_as_entity
11
12
 
12
13
  def <=>(other)
13
- name <=> other.name
14
+ id <=> other.id
14
15
  end
15
16
 
16
- def last_change
17
- branches.map {|b| b.last_changeset }
17
+ def updated!
18
+ @last_updated = Time.now.utc
19
+ save!
20
+ end
21
+
22
+ def hide!
23
+ self.hidden = true
24
+ save!
25
+ end
26
+
27
+ # force string
28
+ def hidden
29
+ @hidden.to_s
30
+ end
31
+
32
+ def hidden?
33
+ @hidden.to_s == "true"
34
+ end
35
+
36
+ def add_branch(branch)
37
+ branch.project = self.name
38
+ branch.save!
39
+
40
+ @repo.relate(:branches, db_object, branch.db_object)
41
+ end
42
+
43
+ def root_branches
44
+ @repo.root_branches(self)
18
45
  end
19
46
 
20
47
  def all_activity
21
- branches.map {|b| b.changesets }.flatten
48
+ @repo.activity(self)
22
49
  end
23
50
 
24
51
  def all_activity_by_date(limiter=nil)
25
52
  raise InvalidArgument("parameter must be a Date") unless limiter.nil? || limiter.is_a?(Time)
26
53
 
27
- activity = all_activity
28
- activity = activity.select {|c| c.created > limiter } unless limiter.nil?
29
-
30
- activity.group_by(&:formatted_created)
54
+ @repo.activity_by_date(self, limiter).group_by(&:formatted_created)
31
55
  end
32
56
 
33
57
  def active_branches
@@ -38,8 +62,16 @@ module TFSGraph
38
62
  branches_with_hidden.reject(&:hidden?)
39
63
  end
40
64
 
65
+ def branches_for_root(root)
66
+ @repo.branches_for_root(self, root)
67
+ end
68
+
69
+ def changesets_for_root(root)
70
+ @repo.changesets_for_root(self, root)
71
+ end
72
+
41
73
  def branches_with_hidden
42
- outgoing(:branches).options(model: Branch).nodes.to_a
74
+ @repo.get_nodes(db_object, :outgoing, :branches, Branch)
43
75
  end
44
76
 
45
77
  %w(master release feature).each do |type|
@@ -51,6 +83,10 @@ module TFSGraph
51
83
  branches_with_hidden.select {|b| b.send "#{type}?" }
52
84
  end
53
85
 
86
+ define_method "active_#{type}s" do
87
+ active_branches.select {|b| b.send("#{type}?") }
88
+ end
89
+
54
90
  define_method "archived_#{type}s" do
55
91
  branches.select {|b| b.send("#{type}?") && b.archived? }
56
92
  end