cobra_commander 0.7.0 → 0.9.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.
@@ -1,12 +0,0 @@
1
- sudo: true
2
- language: ruby
3
- before_install:
4
- - "find /home/travis/.rvm/rubies -wholename '*default/bundler-*.gemspec' -delete"
5
- - gem install bundler:"$BUNDLER_VERSION"
6
- - sudo apt-get -qq install graphviz
7
- - curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 1.13.0
8
- - export PATH="$HOME/.yarn/bin:$PATH"
9
- rvm:
10
- - 2.5.1
11
- env:
12
- - BUNDLER_VERSION=1.17.3
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "cobra_commander/component_tree"
4
-
5
- module CobraCommander
6
- # Represents a dependency tree in a given context, built from a cache
7
- class CachedComponentTree < ComponentTree
8
- attr_reader :dependencies
9
-
10
- def self.from_cache_file(cache_file)
11
- cache = JSON.parse(File.read(cache_file), symbolize_names: true)
12
- new(cache)
13
- end
14
-
15
- def initialize(cache)
16
- super(cache[:name], cache[:path])
17
- @type = cache[:type]
18
- @ancestry = Set.new(cache[:ancestry])
19
- @dependencies = (cache[:dependencies] || []).map do |dep|
20
- CachedComponentTree.new(dep)
21
- end
22
- end
23
- end
24
- end
@@ -1,141 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "cobra_commander/component_tree"
4
- require "open3"
5
-
6
- module CobraCommander
7
- # Represents a dependency tree in a given context
8
- class CalculatedComponentTree < ComponentTree
9
- attr_reader :name, :path
10
-
11
- def initialize(name, path, ancestry = Set.new)
12
- super(name, path)
13
- @ancestry = ancestry
14
- @ruby = Ruby.new(path)
15
- @js = Js.new(path)
16
- @type = type_of_component
17
- end
18
-
19
- def dependencies
20
- @deps ||= begin
21
- deps = @ruby.dependencies + @js.dependencies
22
- deps.sort_by { |dep| dep[:name] }
23
- .map(&method(:dep_representation))
24
- end
25
- end
26
-
27
- private
28
-
29
- def type_of_component
30
- return "Ruby & JS" if @ruby.gem? && @js.node?
31
- return "Ruby" if @ruby.gem?
32
- return "JS" if @js.node?
33
- end
34
-
35
- def dep_representation(dep)
36
- full_path = File.expand_path(File.join(path, dep[:path]))
37
- ancestry = @ancestry + [{ name: @name, path: path, type: @type }]
38
- CalculatedComponentTree.new(dep[:name], full_path, ancestry)
39
- end
40
-
41
- # Calculates ruby dependencies
42
- class Ruby
43
- def initialize(root_path)
44
- @root_path = root_path
45
- end
46
-
47
- def dependencies
48
- @deps ||= begin
49
- return [] unless gem?
50
- gems = bundler_definition.dependencies.select { |dep| path?(dep.source) }
51
- format(gems)
52
- end
53
- end
54
-
55
- def path?(source)
56
- return if source.nil?
57
- source_has_path = source.respond_to?(:path?) ? source.path? : source.is_a_path?
58
- source_has_path && source.path.to_s != "."
59
- end
60
-
61
- def format(deps)
62
- deps.map do |dep|
63
- path = File.join(dep.source.path, dep.name)
64
- { name: dep.name, path: path }
65
- end
66
- end
67
-
68
- def gem?
69
- @gem ||= File.exist?(gemfile_path)
70
- end
71
-
72
- def bundler_definition
73
- ::Bundler::Definition.build(gemfile_path, gemfile_lock_path, nil)
74
- end
75
-
76
- def gemfile_path
77
- File.join(@root_path, "Gemfile")
78
- end
79
-
80
- def gemfile_lock_path
81
- File.join(@root_path, "Gemfile.lock")
82
- end
83
- end
84
-
85
- # Calculates js dependencies
86
- class Js
87
- def initialize(root_path)
88
- @root_path = root_path
89
- end
90
-
91
- def dependencies
92
- @deps ||= begin
93
- return [] unless node?
94
- json = JSON.parse(File.read(package_json_path))
95
- combined_deps(json)
96
- end
97
- end
98
-
99
- def format_dependencies(deps)
100
- return [] if deps.nil?
101
- linked_deps = deps.select { |_, v| v.start_with? "link:" }
102
- linked_deps.map do |_, v|
103
- relational_path = v.split("link:")[1]
104
- dep_name = relational_path.split("/")[-1]
105
- { name: dep_name, path: relational_path }
106
- end
107
- end
108
-
109
- def node?
110
- @node ||= File.exist?(package_json_path)
111
- end
112
-
113
- def package_json_path
114
- File.join(@root_path, "package.json")
115
- end
116
-
117
- def combined_deps(json)
118
- worskpace_dependencies = build_workspaces(json["workspaces"])
119
- dependencies = format_dependencies Hash(json["dependencies"]).merge(Hash(json["devDependencies"]))
120
- (dependencies + worskpace_dependencies).uniq
121
- end
122
-
123
- def build_workspaces(workspaces)
124
- return [] if workspaces.nil?
125
-
126
- yarn_workspaces.map do |_, component|
127
- { name: component["location"].split("/")[-1], path: component["location"] }
128
- end
129
- end
130
-
131
- private
132
-
133
- def yarn_workspaces
134
- @yarn_workspaces ||= begin
135
- output, = Open3.capture2("yarn --json workspaces info", chdir: @root_path)
136
- JSON.parse(JSON.parse(output)["data"])
137
- end
138
- end
139
- end
140
- end
141
- end
@@ -1,69 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "bundler"
4
- require "json"
5
-
6
- module CobraCommander
7
- # Represents a dependency tree in a given context
8
- class ComponentTree
9
- attr_reader :name, :path
10
-
11
- def initialize(name, path)
12
- @name = name
13
- @path = path
14
- end
15
-
16
- def flatten
17
- _flatten(self)
18
- end
19
-
20
- def subtree(name)
21
- _subtree(name, self)
22
- end
23
-
24
- def depends_on?(component_name)
25
- dependencies.any? do |component|
26
- component.name == component_name || component.depends_on?(component_name)
27
- end
28
- end
29
-
30
- def dependents_of(component_name)
31
- depends = depends_on?(component_name) ? self : nil
32
- dependents_below = dependencies.map do |component|
33
- component.dependents_of(component_name)
34
- end
35
- [depends, dependents_below].flatten.compact.uniq(&:name)
36
- end
37
-
38
- def to_h(json_compatible: false)
39
- {
40
- name: @name,
41
- path: path,
42
- type: @type,
43
- ancestry: json_compatible ? @ancestry.to_a : @ancestry,
44
- dependencies: dependencies.map { |dep| dep.to_h(json_compatible: json_compatible) },
45
- }
46
- end
47
-
48
- def to_json
49
- JSON.dump(to_h(json_compatible: true))
50
- end
51
-
52
- private
53
-
54
- def _flatten(component)
55
- component.dependencies.map do |dep|
56
- [dep] + _flatten(dep)
57
- end.flatten.uniq(&:name)
58
- end
59
-
60
- def _subtree(name, tree)
61
- return tree if tree.name == name
62
- tree.dependencies.each do |component|
63
- presence = _subtree(name, component)
64
- return presence if presence
65
- end
66
- nil
67
- end
68
- end
69
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "graphviz"
4
-
5
- module CobraCommander
6
- # Generates graphs of components
7
- class Graph
8
- def initialize(node, format)
9
- @format = format
10
- @node = node
11
- end
12
-
13
- def generate!
14
- return unless valid_format?
15
-
16
- g = GraphViz.new(:G, type: :digraph, concentrate: true)
17
- ([@node] + @node.deep_dependencies).each do |component|
18
- g.add_nodes component.name
19
- g.add_edges component.name, component.dependencies.map(&:name)
20
- end
21
-
22
- output(g)
23
- end
24
-
25
- def output(g)
26
- graph = "graph.#{@format}"
27
- g.output(@format => graph)
28
- puts "Graph generated at #{`pwd`.chomp}/#{graph}"
29
- end
30
-
31
- def valid_format?
32
- return true if @format == "png" || @format == "dot"
33
- puts "FORMAT must be 'png' or 'dot'"
34
- false
35
- end
36
- end
37
- end