tfs_graph 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3024420a800c31fc3676483f1bbd658dda5c22d0
|
4
|
+
data.tar.gz: 527426b7e59e38f884db6876c264d655b11836a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43141894fdff22dd10f8a25864af7cf41875dc611320c7671cfc91a2d60c02ae4a0e2e4a11a7f13044e3f3aee5c713e6be32d1b44c71b8a8099407512380e47e
|
7
|
+
data.tar.gz: a70fad3373c4ac4bddd91e0cfe722abe255f73f90dd6eaf75e150d5cb09e08cc80a69a5fc3c92cc9e35c3f006bf92d29a9e6174219e6505e838d926450ca1455
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.1.0
|
data/Gemfile
CHANGED
@@ -3,17 +3,25 @@ source 'https://rubygems.org'
|
|
3
3
|
# Specify your gem's dependencies in tfs_graph.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
-
gem "related", git: "https://github.com/plukevdh/related.git", branch: "preserve_external_ids"
|
7
|
-
|
8
6
|
group :test do
|
9
7
|
gem 'rspec'
|
10
8
|
gem 'rspec-given'
|
9
|
+
gem 'flexmock'
|
11
10
|
gem 'webmock'
|
12
11
|
gem 'vcr'
|
13
|
-
gem 'factory_girl'
|
14
12
|
end
|
15
13
|
|
16
14
|
group :test, :development do
|
17
15
|
gem "pry"
|
18
16
|
gem 'benchmark-ips'
|
19
|
-
|
17
|
+
gem "related", git: "https://github.com/plukevdh/related.git", branch: "namespace_fix"
|
18
|
+
gem 'timecop'
|
19
|
+
|
20
|
+
gem 'neo4j-core', git: "https://github.com/plukevdh/neo4j-core.git"
|
21
|
+
|
22
|
+
platforms :jruby do
|
23
|
+
gem 'neo4j-community'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
gem 'simplecov', :require => false, :group => :test
|
data/Rakefile
CHANGED
data/lib/tfs_graph.rb
CHANGED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'tfs_graph/tfs_client'
|
2
|
+
require 'tfs_graph/tfs_helpers'
|
3
|
+
require 'tfs_graph/store_helpers'
|
4
|
+
|
5
|
+
module TFSGraph
|
6
|
+
class AbstractStore
|
7
|
+
include TFSClient
|
8
|
+
include TFSHelpers
|
9
|
+
include StoreHelpers
|
10
|
+
|
11
|
+
def fetch_and_cache
|
12
|
+
cache_all fetch_all
|
13
|
+
end
|
14
|
+
|
15
|
+
def fetch_all
|
16
|
+
normalize root_query.run
|
17
|
+
end
|
18
|
+
|
19
|
+
def cache_all(attr_set)
|
20
|
+
attr_set.map {|attrs| cache(attrs) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module TFSGraph
|
2
|
+
class ChangesetTreeBuilder
|
3
|
+
class << self
|
4
|
+
def to_tree(branch, changesets)
|
5
|
+
changesets.map.with_index do |changeset, i|
|
6
|
+
parent = (i == 0) ? branch : changesets[i-1]
|
7
|
+
|
8
|
+
if parent.is_a? TFSGraph::Changeset
|
9
|
+
changeset.parent = parent.id
|
10
|
+
changeset.save!
|
11
|
+
end
|
12
|
+
|
13
|
+
parent.add_child changeset
|
14
|
+
changeset
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def set_branch_merges(changesets)
|
19
|
+
changesets.each do |cs|
|
20
|
+
from = cs.merges.max
|
21
|
+
next unless from
|
22
|
+
|
23
|
+
cs.merge_parent = from.id
|
24
|
+
cs.save!
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module TFSGraph
|
2
|
+
class Behaviors
|
3
|
+
class Neo4jRepository
|
4
|
+
module Branch
|
5
|
+
def find_in_project(project, path)
|
6
|
+
# project.branches.detect {|b| b.path == path }
|
7
|
+
rebuild Neo4j::Label.query(:branch, conditions: {path: path, project: project.name }).first
|
8
|
+
end
|
9
|
+
|
10
|
+
def find_by_path(path)
|
11
|
+
branch = Neo4j::Label.query(:branch, conditions: {path: path}).first
|
12
|
+
raise TFSGraph::Repository::NotFound, "No branch found for #{path}" if branch.nil?
|
13
|
+
|
14
|
+
rebuild branch
|
15
|
+
end
|
16
|
+
|
17
|
+
def absolute_root_for(branch)
|
18
|
+
root = branch
|
19
|
+
proj = project_for_branch branch
|
20
|
+
|
21
|
+
until(root.master?) do
|
22
|
+
root = proj.branches.detect {|b| b.path == root.root }
|
23
|
+
end
|
24
|
+
|
25
|
+
root
|
26
|
+
end
|
27
|
+
|
28
|
+
def project_for_branch(branch)
|
29
|
+
RepositoryRegistry.instance.project_repository.find_by_name branch.project
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def fetch_existing_record(obj)
|
34
|
+
find_by_path(obj.path).db_object
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module TFSGraph
|
2
|
+
class Behaviors
|
3
|
+
class Neo4jRepository
|
4
|
+
module Project
|
5
|
+
ROOT_BRANCH_QUERY = "MATCH (p:project {name: {project}})-[:branches]->(b:branch) WHERE (b.original_path = {path} OR b.root = {path})"
|
6
|
+
ACTIVITY_QUERY = "MATCH (a:project)-[:branches]->(b:branch)-[:changesets]->(c:changeset) where a.name = {name}"
|
7
|
+
|
8
|
+
def create(args)
|
9
|
+
obj = super
|
10
|
+
relate :projects, root, obj.db_object
|
11
|
+
|
12
|
+
obj
|
13
|
+
end
|
14
|
+
|
15
|
+
def all
|
16
|
+
get_nodes(root, :outgoing, :projects, TFSGraph::Project)
|
17
|
+
end
|
18
|
+
|
19
|
+
def active
|
20
|
+
projects = session.query "MATCH (p:project {hidden: 'false'}) RETURN p as `project`, ID(p) as `neo_id`"
|
21
|
+
rebuild_for_type self, projects, :project
|
22
|
+
end
|
23
|
+
|
24
|
+
def find_by_name(name)
|
25
|
+
project = Neo4j::Label.query(:project, conditions: {name: name}).first
|
26
|
+
raise TFSGraph::Repository::NotFound, "No project found for #{name}" if project.nil?
|
27
|
+
|
28
|
+
rebuild project
|
29
|
+
end
|
30
|
+
|
31
|
+
def root_branches(project)
|
32
|
+
roots = session.query "MATCH (p:project {name: {project}})-[:branches]->(b:branch {hidden: 'false', archived: 'false'}) where not has(b.root) RETURN b AS `branch`, ID(b) AS `neo_id`",
|
33
|
+
project: project.name
|
34
|
+
|
35
|
+
rebuild_for_type RepositoryRegistry.branch_repository, roots, :branch
|
36
|
+
end
|
37
|
+
|
38
|
+
def branches_for_root(project, branch)
|
39
|
+
branches = session.query "#{ROOT_BRANCH_QUERY} RETURN b as `branch`, ID(b) as `neo_id`",
|
40
|
+
project: project.name,
|
41
|
+
path: branch.path
|
42
|
+
|
43
|
+
rebuild_for_type RepositoryRegistry.branch_repository, branches, :branch
|
44
|
+
end
|
45
|
+
|
46
|
+
def active_branches_for_root(project, branch)
|
47
|
+
branches = session.query "#{ROOT_BRANCH_QUERY} AND b.archived = 'false' AND b.hidden = 'false' RETURN b as `branch`, ID(b) as `neo_id`",
|
48
|
+
project: project.name,
|
49
|
+
path: branch.path
|
50
|
+
|
51
|
+
rebuild_for_type RepositoryRegistry.branch_repository, branches, :branch
|
52
|
+
end
|
53
|
+
|
54
|
+
def changesets_for_root(project, branch)
|
55
|
+
changesets = session.query "#{ROOT_BRANCH_QUERY} MATCH b-[:changesets]->(c:changeset) RETURN c AS `changeset`, ID(b) as `neo_id` ORDER BY c.id",
|
56
|
+
project: project.name,
|
57
|
+
path: branch.path
|
58
|
+
|
59
|
+
rebuild_for_type RepositoryRegistry.changeset_repository, changesets, :changeset
|
60
|
+
end
|
61
|
+
|
62
|
+
def activity(project)
|
63
|
+
changesets = session.query "#{ACTIVITY_QUERY} RETURN c as `changeset`, ID(b) as `neo_id`",
|
64
|
+
name: project.name
|
65
|
+
|
66
|
+
rebuild_for_type RepositoryRegistry.changeset_repository, changesets, :changeset
|
67
|
+
end
|
68
|
+
|
69
|
+
def activity_by_date(project, time)
|
70
|
+
changesets = session.query "#{ACTIVITY_QUERY} AND c.created >= {time} RETURN c as `changeset`, ID(b) as `neo_id`",
|
71
|
+
{ name: project.name, time: time.utc.to_i }
|
72
|
+
|
73
|
+
rebuild_for_type RepositoryRegistry.changeset_repository, changesets, :changeset
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
def rebuild_for_type(repo, data, key)
|
78
|
+
data.each_slice(2).map do |data,id|
|
79
|
+
repo.rebuild_from_query data[key]['data'], id[:neo_id]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def fetch_existing_record(obj)
|
84
|
+
find_by_name(obj.name).db_object
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module TFSGraph
|
2
|
+
class Behaviors
|
3
|
+
class RelatedRepository
|
4
|
+
module Branch
|
5
|
+
def find_in_project(project, path)
|
6
|
+
project.branches.detect {|b| b.path == path }
|
7
|
+
end
|
8
|
+
|
9
|
+
def absolute_root_for(branch)
|
10
|
+
root = branch
|
11
|
+
proj = project_for_branch branch
|
12
|
+
|
13
|
+
until(root.master?) do
|
14
|
+
root = proj.branches.detect {|b| b.path == root.root }
|
15
|
+
end
|
16
|
+
|
17
|
+
root
|
18
|
+
end
|
19
|
+
|
20
|
+
def project_for_branch(branch)
|
21
|
+
RepositoryRegistry.instance.project_repository.find_by_name branch.project
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module TFSGraph
|
2
|
+
class Behaviors
|
3
|
+
class RelatedRepository
|
4
|
+
module Project
|
5
|
+
def create(args)
|
6
|
+
obj = super
|
7
|
+
relate :projects, root, obj.db_object
|
8
|
+
|
9
|
+
obj
|
10
|
+
end
|
11
|
+
|
12
|
+
def all
|
13
|
+
get_nodes(root, :outgoing, :projects, TFSGraph::Project)
|
14
|
+
end
|
15
|
+
|
16
|
+
def active
|
17
|
+
all.reject &:hidden?
|
18
|
+
end
|
19
|
+
|
20
|
+
def find_by_name(name)
|
21
|
+
project = all.detect {|p| p.name == name }
|
22
|
+
raise TFSGraph::Repository::NotFound, "No project found for #{name}" if project.nil?
|
23
|
+
|
24
|
+
project
|
25
|
+
end
|
26
|
+
|
27
|
+
def branches_for_root(project, root)
|
28
|
+
project.branches.select {|b| b.root == branch.path || b.original_path == branch.path}
|
29
|
+
end
|
30
|
+
|
31
|
+
def changesets_for_root(project, root)
|
32
|
+
branches_for_root(project, root).map(&:changesets).flatten.sort
|
33
|
+
end
|
34
|
+
|
35
|
+
def activity(project)
|
36
|
+
project.branches.map {|b| b.changesets }.flatten
|
37
|
+
end
|
38
|
+
|
39
|
+
def activity_by_date(project, date)
|
40
|
+
activity = activity(project)
|
41
|
+
activity = activity.select {|c| c.created > date } unless date.nil?
|
42
|
+
|
43
|
+
activity
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/tfs_graph/branch.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
|
-
require 'tfs_graph/
|
1
|
+
require 'tfs_graph/persistable_entity'
|
2
2
|
require 'tfs_graph/tfs_helpers'
|
3
3
|
|
4
4
|
module TFSGraph
|
5
|
-
class Branch <
|
5
|
+
class Branch < PersistableEntity
|
6
6
|
extend TFSHelpers
|
7
|
-
extend Comparable
|
8
7
|
|
9
8
|
SCHEMA = {
|
10
9
|
original_path: {key: "Path", type: String},
|
@@ -12,10 +11,11 @@ module TFSGraph
|
|
12
11
|
project: {converter: ->(path) { branch_project(path) }, key: "Path", type: String},
|
13
12
|
name: {converter: ->(path) { branch_path_to_name(path) }, key: "Path", type: String},
|
14
13
|
root: {converter: ->(path) { repath_archive(server_path_to_odata_path(path)) if path }, key: "ParentBranch", type: String},
|
15
|
-
created: {key: "DateCreated", type:
|
14
|
+
created: {key: "DateCreated", type: Time},
|
16
15
|
type: {default: "Feature", type: Integer},
|
17
16
|
archived: {default: false, type: String},
|
18
|
-
hidden: {default: false, type: String}
|
17
|
+
hidden: {default: false, type: String},
|
18
|
+
last_updated: {type: Time, default: Time.at(0).utc}
|
19
19
|
}
|
20
20
|
|
21
21
|
BRANCH_TYPES = [
|
@@ -29,7 +29,12 @@ module TFSGraph
|
|
29
29
|
|
30
30
|
act_as_entity
|
31
31
|
|
32
|
-
|
32
|
+
def initialize(repo, args)
|
33
|
+
super
|
34
|
+
|
35
|
+
detect_type
|
36
|
+
detect_archived
|
37
|
+
end
|
33
38
|
|
34
39
|
BRANCH_TYPES.each do |t|
|
35
40
|
define_method "#{t}?".to_sym do
|
@@ -37,6 +42,14 @@ module TFSGraph
|
|
37
42
|
end
|
38
43
|
end
|
39
44
|
|
45
|
+
def archived
|
46
|
+
@archived.to_s
|
47
|
+
end
|
48
|
+
|
49
|
+
def hidden
|
50
|
+
@hidden.to_s
|
51
|
+
end
|
52
|
+
|
40
53
|
def archived?
|
41
54
|
archived.to_s == "true"
|
42
55
|
end
|
@@ -45,40 +58,40 @@ module TFSGraph
|
|
45
58
|
hidden.to_s == "true"
|
46
59
|
end
|
47
60
|
|
61
|
+
def active?
|
62
|
+
!hidden? && !archived?
|
63
|
+
end
|
64
|
+
|
48
65
|
def named_type
|
49
66
|
BRANCH_TYPES[type]
|
50
67
|
end
|
51
68
|
|
69
|
+
def updated!
|
70
|
+
@last_updated = Time.now.utc
|
71
|
+
save!
|
72
|
+
end
|
73
|
+
|
74
|
+
def updated_since?(date)
|
75
|
+
@last_updated > date
|
76
|
+
end
|
77
|
+
|
52
78
|
def hide!
|
53
79
|
self.hidden = true
|
54
|
-
save
|
80
|
+
save!
|
55
81
|
end
|
56
82
|
|
57
83
|
def archive!
|
58
84
|
self.archived = true
|
59
|
-
save
|
85
|
+
save!
|
60
86
|
end
|
61
87
|
|
62
88
|
def rootless?
|
63
89
|
!master? && root.empty?
|
64
90
|
end
|
65
91
|
|
66
|
-
def type_index(name)
|
67
|
-
BRANCH_TYPES.index(name.to_sym)
|
68
|
-
end
|
69
|
-
|
70
92
|
# returns a branch
|
71
93
|
def absolute_root
|
72
|
-
@absolute_root ||=
|
73
|
-
item = self
|
74
|
-
proj = ProjectStore.find_cached project
|
75
|
-
|
76
|
-
until(item.master?) do
|
77
|
-
item = proj.branches.detect {|branch| branch.path == item.root }
|
78
|
-
end
|
79
|
-
|
80
|
-
item
|
81
|
-
end
|
94
|
+
@absolute_root ||= @repo.absolute_root_for(self)
|
82
95
|
end
|
83
96
|
|
84
97
|
def branch?
|
@@ -87,11 +100,27 @@ module TFSGraph
|
|
87
100
|
|
88
101
|
# branches this one touches or is touched
|
89
102
|
def related_branches
|
90
|
-
|
103
|
+
@repo.get_nodes(db_object, :incoming, :related, Branch).map &:id
|
104
|
+
end
|
105
|
+
|
106
|
+
def merged_changesets
|
107
|
+
@repo.get_nodes(db_object, :outgoing, :included, Changeset)
|
108
|
+
end
|
109
|
+
|
110
|
+
def add_changeset(changeset)
|
111
|
+
# attach branch path
|
112
|
+
changeset.branch_path = self.path
|
113
|
+
changeset.save!
|
114
|
+
|
115
|
+
@repo.relate(:changesets, self.db_object, changeset.db_object)
|
116
|
+
end
|
117
|
+
|
118
|
+
def add_child(changeset)
|
119
|
+
@repo.relate(:child, self.db_object, changeset.db_object)
|
91
120
|
end
|
92
121
|
|
93
122
|
def changesets
|
94
|
-
|
123
|
+
@repo.get_nodes(db_object, :outgoing, :changesets, Changeset)
|
95
124
|
end
|
96
125
|
|
97
126
|
def contributors
|
@@ -99,7 +128,7 @@ module TFSGraph
|
|
99
128
|
end
|
100
129
|
|
101
130
|
def root_changeset
|
102
|
-
@root
|
131
|
+
@root = @repo.get_nodes(db_object, :outgoing, :child, Changeset).first if (@root.nil? || @root.empty?)
|
103
132
|
end
|
104
133
|
|
105
134
|
def last_changeset
|
@@ -108,20 +137,30 @@ module TFSGraph
|
|
108
137
|
|
109
138
|
def ahead_of_master
|
110
139
|
return 0 unless absolute_root
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
140
|
+
my_changes = changesets
|
141
|
+
root_changes = absolute_root.merged_changesets
|
142
|
+
|
143
|
+
# get intersection between root and this branch
|
144
|
+
intersect = root_changes & my_changes
|
145
|
+
# get difference of intersect with my changes
|
146
|
+
diff = my_changes - intersect
|
147
|
+
|
148
|
+
diff.count
|
115
149
|
end
|
116
150
|
|
117
151
|
# gets the set of changesets that exist in both root and self
|
118
152
|
# then gets a diff of that set and the root.
|
119
153
|
def behind_master
|
120
154
|
return 0 unless absolute_root
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
155
|
+
my_changes = merged_changesets
|
156
|
+
root_changes = absolute_root.changesets
|
157
|
+
|
158
|
+
# get intersect between my changes and the root
|
159
|
+
intersect = my_changes & root_changes
|
160
|
+
# get diff of root changes to intersect
|
161
|
+
diff = root_changes - intersect
|
162
|
+
|
163
|
+
diff.count
|
125
164
|
end
|
126
165
|
|
127
166
|
def <=>(other)
|
@@ -129,20 +168,28 @@ module TFSGraph
|
|
129
168
|
end
|
130
169
|
|
131
170
|
def as_json(options={})
|
132
|
-
|
133
|
-
|
171
|
+
results = super
|
172
|
+
results[:related_branches] = related_branches
|
173
|
+
results[:id] = id
|
174
|
+
|
175
|
+
results
|
176
|
+
end
|
177
|
+
|
178
|
+
def type_index(name)
|
179
|
+
BRANCH_TYPES.index(name.to_sym)
|
134
180
|
end
|
135
181
|
|
136
182
|
private
|
183
|
+
|
137
184
|
def detect_type
|
138
|
-
return self.type = type_index(:master) if (root.empty?)
|
185
|
+
return self.type = type_index(:master) if (root.nil? || root.empty?)
|
139
186
|
return self.type = type_index(:release) if !(name =~ RELEASE_MATCHER).nil?
|
140
187
|
self.type = type_index(:feature)
|
141
188
|
nil
|
142
189
|
end
|
143
190
|
|
144
191
|
def detect_archived
|
145
|
-
self.archived = ARCHIVED_FLAGS.any? {|flag| original_path.include?
|
192
|
+
self.archived = ARCHIVED_FLAGS.any? {|flag| original_path && original_path.include?(flag) }
|
146
193
|
nil
|
147
194
|
end
|
148
195
|
|