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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/Gemfile +12 -4
- data/Rakefile +1 -0
- data/lib/tfs_graph.rb +1 -2
- data/lib/tfs_graph/abstract_store.rb +23 -0
- data/lib/tfs_graph/associators/branch_associator.rb +1 -1
- data/lib/tfs_graph/associators/changeset_tree_builder.rb +29 -0
- data/lib/tfs_graph/behaviors.rb +9 -0
- data/lib/tfs_graph/behaviors/neo4j_repository/branch.rb +39 -0
- data/lib/tfs_graph/behaviors/neo4j_repository/changeset.rb +12 -0
- data/lib/tfs_graph/behaviors/neo4j_repository/project.rb +89 -0
- data/lib/tfs_graph/behaviors/related_repository/branch.rb +26 -0
- data/lib/tfs_graph/behaviors/related_repository/changeset.rb +8 -0
- data/lib/tfs_graph/behaviors/related_repository/project.rb +48 -0
- data/lib/tfs_graph/branch.rb +84 -37
- data/lib/tfs_graph/branch/branch_archive_handler.rb +10 -6
- data/lib/tfs_graph/branch/branch_store.rb +13 -26
- data/lib/tfs_graph/changeset.rb +46 -25
- data/lib/tfs_graph/changeset/changeset_normalizer.rb +1 -0
- data/lib/tfs_graph/changeset/changeset_store.rb +13 -36
- data/lib/tfs_graph/changeset_merge.rb +20 -18
- data/lib/tfs_graph/changeset_merge/changeset_merge_store.rb +13 -10
- data/lib/tfs_graph/config.rb +12 -4
- data/lib/tfs_graph/entity.rb +34 -6
- data/lib/tfs_graph/extensions.rb +27 -0
- data/lib/tfs_graph/graph_populator.rb +9 -1
- data/lib/tfs_graph/persistable_entity.rb +60 -0
- data/lib/tfs_graph/populators/everything.rb +16 -4
- data/lib/tfs_graph/populators/for_archived_branch.rb +28 -0
- data/lib/tfs_graph/populators/for_branch.rb +35 -0
- data/lib/tfs_graph/populators/for_project.rb +22 -5
- data/lib/tfs_graph/populators/since_date.rb +21 -5
- data/lib/tfs_graph/populators/since_last.rb +22 -10
- data/lib/tfs_graph/populators/utilities.rb +4 -19
- data/lib/tfs_graph/project.rb +49 -13
- data/lib/tfs_graph/project/project_store.rb +13 -22
- data/lib/tfs_graph/repository.rb +78 -0
- data/lib/tfs_graph/repository/neo4j_repository.rb +97 -0
- data/lib/tfs_graph/repository/related_repository.rb +89 -0
- data/lib/tfs_graph/repository_registry.rb +60 -0
- data/lib/tfs_graph/server_registry.rb +45 -0
- data/lib/tfs_graph/store_helpers.rb +4 -5
- data/lib/tfs_graph/version.rb +1 -1
- data/schema.cypher +7 -0
- data/spec/branch_spec.rb +120 -0
- data/spec/neo4j_repository_integration_spec.rb +346 -0
- data/spec/persistable_entity_spec.rb +91 -0
- data/spec/project_spec.rb +29 -0
- data/spec/related_repository_integration_spec.rb +328 -0
- data/spec/repository_registry_spec.rb +48 -0
- data/spec/repository_spec.rb +73 -0
- data/spec/server_registery_spec.rb +36 -0
- data/spec/spec_helper.rb +12 -24
- data/tfs_graph.gemspec +3 -2
- metadata +67 -21
- data/lib/tfs_graph/associators/changeset_tree_creator.rb +0 -19
- 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/
|
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
|
-
|
10
|
-
branches = collect_branches(project)
|
11
|
-
branches.map {|branch| collect_changesets(branch) }
|
9
|
+
projects = ProjectStore.fetch_and_cache
|
12
10
|
|
13
|
-
|
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
|
-
|
12
|
-
|
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
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
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.
|
8
|
-
|
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
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
16
|
-
|
14
|
+
def find_project(name)
|
15
|
+
TFSGraph::RepositoryRegistry.project_repository.find_by_name name
|
17
16
|
end
|
18
17
|
|
19
|
-
def
|
20
|
-
|
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
|
data/lib/tfs_graph/project.rb
CHANGED
@@ -1,33 +1,57 @@
|
|
1
|
-
require 'tfs_graph/
|
1
|
+
require 'tfs_graph/persistable_entity'
|
2
2
|
|
3
3
|
module TFSGraph
|
4
|
-
class Project <
|
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
|
-
|
14
|
+
id <=> other.id
|
14
15
|
end
|
15
16
|
|
16
|
-
def
|
17
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|