cobra_commander 0.4.0 → 0.7.0

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.
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "open3"
4
+
5
+ require_relative "yarn/package"
6
+ require_relative "yarn/package_repo"
7
+
8
+ module CobraCommander
9
+ module Dependencies
10
+ # Yarn workspace components source for an umbrella
11
+ class YarnWorkspace
12
+ attr_reader :packages
13
+
14
+ def initialize(root_path)
15
+ @repo = Yarn::PackageRepo.new
16
+ @root_package = Yarn::Package.new(root_path)
17
+ @repo.load_linked_specs(@root_package)
18
+ load_workspace_packages
19
+ end
20
+
21
+ def path
22
+ @root_package.path
23
+ end
24
+
25
+ def dependencies
26
+ (workspace_spec.keys | @root_package.dependencies.keys).map(&method(:untag))
27
+ end
28
+
29
+ def components
30
+ @repo.specs.map do |spec|
31
+ { path: spec.path, name: untag(spec.name), dependencies: spec.dependencies.keys.map(&method(:untag)) }
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def load_workspace_packages
38
+ workspace_spec.map do |_name, spec|
39
+ @repo.load_spec File.expand_path(File.join(@root_package.path, "..", spec["location"]))
40
+ end
41
+ end
42
+
43
+ def workspace_spec
44
+ @workspace_spec ||= begin
45
+ output, = Open3.capture2("yarn workspaces --json info", chdir: File.dirname(@root_package.path))
46
+ JSON.parse(JSON.parse(output)["data"])
47
+ end
48
+ end
49
+
50
+ def untag(name)
51
+ name.gsub(@root_package.project_tag, "")
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CobraCommander
4
+ # Execute commands on all components of a ComponentTree
5
+ class Executor
6
+ def initialize(components)
7
+ @components = components
8
+ end
9
+
10
+ def exec(command, printer = $stdout)
11
+ @components.each do |component|
12
+ component.root_paths.each do |path|
13
+ printer.puts "===> #{component.name} (#{path})"
14
+ output, = Open3.capture2e(command, chdir: path, unsetenv_others: true)
15
+ printer.puts output
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,36 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "graphviz"
4
- require "cobra_commander/component_tree"
5
4
 
6
5
  module CobraCommander
7
6
  # Generates graphs of components
8
7
  class Graph
9
- def initialize(app_path, format)
8
+ def initialize(node, format)
10
9
  @format = format
11
- @tree = ComponentTree.new(app_path).to_h
10
+ @node = node
12
11
  end
13
12
 
14
13
  def generate!
15
14
  return unless valid_format?
16
15
 
17
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
18
21
 
19
- app_node = g.add_nodes(@tree[:name])
20
- map_nodes(g, app_node, @tree)
21
22
  output(g)
22
23
  end
23
24
 
24
- private
25
-
26
- def map_nodes(g, parent_node, tree)
27
- tree[:dependencies].each do |dep|
28
- node = g.find_node(dep[:name]) || g.add_nodes(dep[:name])
29
- g.add_edges(parent_node, node)
30
- map_nodes(g, node, dep)
31
- end
32
- end
33
-
34
25
  def output(g)
35
26
  graph = "graph.#{@format}"
36
27
  g.output(@format => graph)
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CobraCommander
4
+ # Module for pretty printing dependency trees
5
+ module Output
6
+ def self.print(node, format)
7
+ output = format == "list" ? Output::FlatList.new(node) : Output::Tree.new(node)
8
+ puts output.to_s
9
+ end
10
+
11
+ # Flattens a tree and prints unique items
12
+ class FlatList
13
+ def initialize(tree)
14
+ @tree = tree
15
+ end
16
+
17
+ def to_s
18
+ @tree.deep_dependencies.map(&:name).sort
19
+ end
20
+ end
21
+
22
+ # Prints the tree in a nice tree form
23
+ class Tree
24
+ attr_accessor :tree
25
+
26
+ SPACE = " "
27
+ BAR = "│   "
28
+ TEE = "├── "
29
+ CORNER = "└── "
30
+
31
+ def initialize(node)
32
+ @node = node
33
+ end
34
+
35
+ def to_s
36
+ StringIO.new.tap do |io|
37
+ io.puts @node.name
38
+ list_dependencies(io, @node)
39
+ end.string
40
+ end
41
+
42
+ private
43
+
44
+ def list_dependencies(io, node, outdents = [])
45
+ node.dependencies.each do |dep|
46
+ decide_on_line(io, node, dep, outdents)
47
+ end
48
+ nil
49
+ end
50
+
51
+ def decide_on_line(io, parent, dep, outdents)
52
+ if parent.dependencies.last != dep
53
+ add_tee(io, outdents, dep)
54
+ else
55
+ add_corner(io, outdents, dep)
56
+ end
57
+ end
58
+
59
+ def add_tee(io, outdents, dep)
60
+ io.puts line(outdents, TEE, dep.name)
61
+ list_dependencies(io, dep, (outdents + [BAR]))
62
+ end
63
+
64
+ def add_corner(io, outdents, dep)
65
+ io.puts line(outdents, CORNER, dep.name)
66
+ list_dependencies(io, dep, (outdents + [SPACE]))
67
+ end
68
+
69
+ def line(outdents, sym, name)
70
+ (outdents + [sym] + [name]).join
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CobraCommander
4
+ # An umbrella application
5
+ class Umbrella
6
+ attr_reader :name, :path
7
+
8
+ def initialize(name, path)
9
+ @root_component = Component.new(self, name)
10
+ @path = path
11
+ @components = {}
12
+ end
13
+
14
+ def find(name)
15
+ @components[name]
16
+ end
17
+
18
+ def root
19
+ @root_component
20
+ end
21
+
22
+ def resolve(component_root_path)
23
+ return root if root.root_paths.include?(component_root_path)
24
+ components.find do |component|
25
+ component.root_paths.include?(component_root_path)
26
+ end
27
+ end
28
+
29
+ def add_source(key, source)
30
+ @root_component.add_source key, source.path, source.dependencies
31
+ source.components.each do |path:, name:, dependencies:|
32
+ @components[name] ||= Component.new(self, name)
33
+ @components[name].add_source key, path, dependencies
34
+ end
35
+ end
36
+
37
+ def components
38
+ @components.values
39
+ end
40
+
41
+ def dependents_of(component)
42
+ find(component)&.deep_dependents
43
+ &.sort_by(&:name)
44
+ end
45
+
46
+ def dependencies_of(name)
47
+ find(name)&.deep_dependencies
48
+ &.sort_by(&:name)
49
+ end
50
+ end
51
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CobraCommander
4
- VERSION = "0.4.0"
4
+ VERSION = "0.7.0"
5
5
  end
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": [
3
+ "config:base"
4
+ ],
5
+ "ignorePaths": [
6
+ "spec/fixtures"
7
+ ]
8
+ }
metadata CHANGED
@@ -1,30 +1,37 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cobra_commander
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Langfeld
8
8
  - Garett Arrowood
9
+ - Carlos Palhares
9
10
  autorequire:
10
11
  bindir: exe
11
12
  cert_chain: []
12
- date: 2018-09-06 00:00:00.000000000 Z
13
+ date: 2020-07-08 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: thor
16
17
  requirement: !ruby/object:Gem::Requirement
17
18
  requirements:
18
- - - "~>"
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '2.0'
22
+ - - ">="
19
23
  - !ruby/object:Gem::Version
20
- version: 0.19.4
24
+ version: 0.18.1
21
25
  type: :runtime
22
26
  prerelease: false
23
27
  version_requirements: !ruby/object:Gem::Requirement
24
28
  requirements:
25
- - - "~>"
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '2.0'
32
+ - - ">="
26
33
  - !ruby/object:Gem::Version
27
- version: 0.19.4
34
+ version: 0.18.1
28
35
  - !ruby/object:Gem::Dependency
29
36
  name: ruby-graphviz
30
37
  requirement: !ruby/object:Gem::Requirement
@@ -45,14 +52,14 @@ dependencies:
45
52
  requirements:
46
53
  - - "~>"
47
54
  - !ruby/object:Gem::Version
48
- version: '1.13'
55
+ version: '1.17'
49
56
  type: :development
50
57
  prerelease: false
51
58
  version_requirements: !ruby/object:Gem::Requirement
52
59
  requirements:
53
60
  - - "~>"
54
61
  - !ruby/object:Gem::Version
55
- version: '1.13'
62
+ version: '1.17'
56
63
  - !ruby/object:Gem::Dependency
57
64
  name: rake
58
65
  requirement: !ruby/object:Gem::Requirement
@@ -144,11 +151,13 @@ description: |
144
151
  email:
145
152
  - blangfeld@powerhrg.com
146
153
  - garett.arrowood@powerhrg.com
154
+ - carlos.palhares@powerhrg.com
147
155
  executables:
148
156
  - cobra
149
157
  extensions: []
150
158
  extra_rdoc_files: []
151
159
  files:
160
+ - ".editorconfig"
152
161
  - ".gitignore"
153
162
  - ".rspec"
154
163
  - ".rubocop.yml"
@@ -167,12 +176,23 @@ files:
167
176
  - exe/cobra
168
177
  - lib/cobra_commander.rb
169
178
  - lib/cobra_commander/affected.rb
179
+ - lib/cobra_commander/cached_component_tree.rb
180
+ - lib/cobra_commander/calculated_component_tree.rb
170
181
  - lib/cobra_commander/change.rb
171
182
  - lib/cobra_commander/cli.rb
183
+ - lib/cobra_commander/component.rb
172
184
  - lib/cobra_commander/component_tree.rb
173
- - lib/cobra_commander/formatted_output.rb
185
+ - lib/cobra_commander/dependencies.rb
186
+ - lib/cobra_commander/dependencies/bundler.rb
187
+ - lib/cobra_commander/dependencies/yarn/package.rb
188
+ - lib/cobra_commander/dependencies/yarn/package_repo.rb
189
+ - lib/cobra_commander/dependencies/yarn_workspace.rb
190
+ - lib/cobra_commander/executor.rb
174
191
  - lib/cobra_commander/graph.rb
192
+ - lib/cobra_commander/output.rb
193
+ - lib/cobra_commander/umbrella.rb
175
194
  - lib/cobra_commander/version.rb
195
+ - renovate.json
176
196
  homepage: http://tech.powerhrg.com/cobra_commander/
177
197
  licenses:
178
198
  - MIT
@@ -1,76 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "cobra_commander/component_tree"
4
-
5
- module CobraCommander
6
- # Formats CLI ls output
7
- class FormattedOutput
8
- attr_accessor :tree
9
-
10
- SPACE = " "
11
- BAR = "│   "
12
- TEE = "├── "
13
- CORNER = "└── "
14
-
15
- def initialize(app_path)
16
- @tree = ComponentTree.new(app_path).to_h
17
- end
18
-
19
- def run!
20
- puts @tree[:name]
21
- list_dependencies(@tree)
22
- nil
23
- end
24
-
25
- def dependencies_of!(component_name, format)
26
- @component_name = component_name
27
-
28
- results = @tree[:dependencies].map do |component|
29
- if @component_name == component[:name]
30
- @tree[:name]
31
- elsif dependency?(component)
32
- component[:name]
33
- end
34
- end.compact
35
-
36
- "list" == format ? results : results.size
37
- end
38
-
39
- private
40
-
41
- def dependency?(deps)
42
- deps[:dependencies].each do |dep|
43
- return true if @component_name == dep[:name] || dependency?(dep)
44
- end
45
- false
46
- end
47
-
48
- def list_dependencies(deps, outdents = [])
49
- deps[:dependencies].each do |dep|
50
- decide_on_line(deps, dep, outdents)
51
- end
52
- end
53
-
54
- def decide_on_line(parent, dep, outdents)
55
- if parent[:dependencies].last != dep
56
- add_tee(outdents, dep)
57
- else
58
- add_corner(outdents, dep)
59
- end
60
- end
61
-
62
- def add_tee(outdents, dep)
63
- puts line(outdents, TEE, dep[:name])
64
- list_dependencies(dep, (outdents + [BAR]))
65
- end
66
-
67
- def add_corner(outdents, dep)
68
- puts line(outdents, CORNER, dep[:name])
69
- list_dependencies(dep, (outdents + [SPACE]))
70
- end
71
-
72
- def line(outdents, sym, name)
73
- (outdents + [sym] + [name]).join
74
- end
75
- end
76
- end