cobra_commander 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dfee6f7a8cb59dfa182b31bb4ef7b95615c76336150e6519facb0c5d2deb2eb5
4
- data.tar.gz: 492bde3922963729f4765a1ab245467429167135fb8d431d8a3461db4d86c1b7
3
+ metadata.gz: '037980fd32c80d6ea74549f570cf31cf88d92d4a2702f4ab6568a68bf6160893'
4
+ data.tar.gz: 46da654f6a423723487f595bfe1f397cb32208ef995634396e508594fd51b5fd
5
5
  SHA512:
6
- metadata.gz: e2a87ebda5fcf0d6570714ec750cb3b9eba61d5f8afa89e5a9ab090a0e5aa2248f498048d1253a344052d6aca59f7cb69ca6be0179472ae0a2317a433f071f89
7
- data.tar.gz: f3dcbceadec7c318d5311aee82faa2bfd30f97a27b2f245485e25139de685659a7b1d0112d0c51dca13f387676afd41cc322ddb1b3f1445dc809821208e20578
6
+ metadata.gz: aa50298aacd18c53e98f73859e3bd787def474fbd7854f67c014b6c35ca1ea2ee82b84d8af1ac25d47ff8b3317410951a2e021fead7d19eb4d0dabfafd8e89ab
7
+ data.tar.gz: b8b5e75884f2c3b49839c14654f0b729ba9247fb67e90d86b4946fe896f5bfe4da39149f5a79a2d6bb63507e862a91b30817b99905ebd77d95a04a8b839163e0
data/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## Version 0.6.0 - 2019-07-03
6
+
7
+ * Tracks package.json `workspaces` in addition to `dependencies` and `devDependencies`. PR [#31](https://github.com/powerhome/cobra_commander/pull/31)
8
+ * Permits caching the component tree of a project on disk to avoid calculating it repeatedly on subsequent cobra invocations.
9
+
5
10
  ## Version 0.5.1 - 2018-10-15
6
11
 
7
12
  * Fix a bug with dependencies_of where it wouldn't match components further down the list of umbrella's dependencies
data/README.md CHANGED
@@ -28,20 +28,20 @@ Or install it yourself as:
28
28
 
29
29
  ```bash
30
30
  Commands:
31
- cobra changes APP_PATH [--results=RESULTS] [--branch=BRANCH] # Prints list of changed files
32
- cobra graph APP_PATH [--format=FORMAT] # Outputs graph
33
- cobra help [COMMAND] # Describe available commands or one specific command
34
- cobra ls APP_PATH [--format=list|tree] # Prints tree of components for an app
35
- cobra version # Prints version
36
- cobra do [command] # Executes the command in the context of each component
37
- cobra dependencies_of [component] [--app=/path/to/app] [--format=list|tree] # Lists the dependencies of the component in the app context
38
- cobra dependents_of [component] [--app=/path/to/app] [--format=list|count] # Lists or counts the components that depend directly or indirectly on the given component
39
- cobra version # Prints version
31
+ cobra cache APP_PATH CACHE_PATH # Caches a representation of the component structure of the app
32
+ cobra changes APP_PATH [--results=RESULTS] [--branch=BRANCH] [--cache=nil] # Prints list of changed files
33
+ cobra dependencies_of [component] [--app=pwd] [--format=FORMAT] [--cache=nil] # Outputs a list of components that [component] depends on within [app] context
34
+ cobra dependents_of [component] [--app=pwd] [--format=FORMAT] [--cache=nil] # Outputs count of components in [app] dependent on [component]
35
+ cobra do [command] [--app=pwd] [--cache=nil] # Executes the command in the context of each component in [app]
36
+ cobra graph APP_PATH [--format=FORMAT] [--cache=nil] # Outputs graph
37
+ cobra help [COMMAND] # Describe available commands or one specific command
38
+ cobra ls [app_path] [--app=pwd] [--format=FORMAT] [--cache=nil] # Prints tree of components for an app
39
+ cobra version # Prints version
40
40
  ```
41
41
 
42
42
  ## Development
43
43
 
44
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
44
+ After checking out the repo, run `bin/setup` to install dependencies. You will also need to install `graphviz` by running `brew install graphviz`. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
45
45
 
46
46
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
47
47
 
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "cobra_commander/cli"
4
- require "cobra_commander/component_tree"
4
+ require "cobra_commander/cached_component_tree"
5
+ require "cobra_commander/calculated_component_tree"
5
6
  require "cobra_commander/version"
6
7
  require "cobra_commander/graph"
7
8
  require "cobra_commander/change"
@@ -16,6 +17,10 @@ module CobraCommander
16
17
  UMBRELLA_APP_NAME = "App"
17
18
 
18
19
  def self.umbrella_tree(path)
19
- ComponentTree.new(UMBRELLA_APP_NAME, path)
20
+ CalculatedComponentTree.new(UMBRELLA_APP_NAME, path)
21
+ end
22
+
23
+ def self.tree_from_cache(cache_file)
24
+ CachedComponentTree.from_cache_file(cache_file)
20
25
  end
21
26
  end
@@ -0,0 +1,24 @@
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
@@ -0,0 +1,146 @@
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
7
+ class CalculatedComponentTree < ComponentTree
8
+ attr_reader :name, :path
9
+
10
+ def initialize(name, path, ancestry = Set.new)
11
+ super(name, path)
12
+ @ancestry = ancestry
13
+ @ruby = Ruby.new(path)
14
+ @js = Js.new(path)
15
+ @type = type_of_component
16
+ end
17
+
18
+ def dependencies
19
+ @deps ||= begin
20
+ deps = @ruby.dependencies + @js.dependencies
21
+ deps.sort_by { |dep| dep[:name] }
22
+ .map(&method(:dep_representation))
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def type_of_component
29
+ return "Ruby & JS" if @ruby.gem? && @js.node?
30
+ return "Ruby" if @ruby.gem?
31
+ return "JS" if @js.node?
32
+ end
33
+
34
+ def dep_representation(dep)
35
+ full_path = File.expand_path(File.join(path, dep[:path]))
36
+ ancestry = @ancestry + [{ name: @name, path: path, type: @type }]
37
+ CalculatedComponentTree.new(dep[:name], full_path, ancestry)
38
+ end
39
+
40
+ # Calculates ruby dependencies
41
+ class Ruby
42
+ def initialize(root_path)
43
+ @root_path = root_path
44
+ end
45
+
46
+ def dependencies
47
+ @deps ||= begin
48
+ return [] unless gem?
49
+ gems = bundler_definition.dependencies.select { |dep| path?(dep.source) }
50
+ format(gems)
51
+ end
52
+ end
53
+
54
+ def path?(source)
55
+ return if source.nil?
56
+ source_has_path = source.respond_to?(:path?) ? source.path? : source.is_a_path?
57
+ source_has_path && source.path.to_s != "."
58
+ end
59
+
60
+ def format(deps)
61
+ deps.map do |dep|
62
+ path = File.join(dep.source.path, dep.name)
63
+ { name: dep.name, path: path }
64
+ end
65
+ end
66
+
67
+ def gem?
68
+ @gem ||= File.exist?(gemfile_path)
69
+ end
70
+
71
+ def bundler_definition
72
+ ::Bundler::Definition.build(gemfile_path, gemfile_lock_path, nil)
73
+ end
74
+
75
+ def gemfile_path
76
+ File.join(@root_path, "Gemfile")
77
+ end
78
+
79
+ def gemfile_lock_path
80
+ File.join(@root_path, "Gemfile.lock")
81
+ end
82
+ end
83
+
84
+ # Calculates js dependencies
85
+ class Js
86
+ def initialize(root_path)
87
+ @root_path = root_path
88
+ end
89
+
90
+ def dependencies
91
+ @deps ||= begin
92
+ return [] unless node?
93
+ json = JSON.parse(File.read(package_json_path))
94
+ combined_deps(json)
95
+ end
96
+ end
97
+
98
+ def format_dependencies(deps)
99
+ return [] if deps.nil?
100
+ linked_deps = deps.select { |_, v| v.start_with? "link:" }
101
+ linked_deps.map do |_, v|
102
+ relational_path = v.split("link:")[1]
103
+ dep_name = relational_path.split("/")[-1]
104
+ { name: dep_name, path: relational_path }
105
+ end
106
+ end
107
+
108
+ def node?
109
+ @node ||= File.exist?(package_json_path)
110
+ end
111
+
112
+ def package_json_path
113
+ File.join(@root_path, "package.json")
114
+ end
115
+
116
+ def combined_deps(json)
117
+ worskpace_dependencies = build_workspaces(json["workspaces"])
118
+ dependencies = format_dependencies Hash(json["dependencies"]).merge(Hash(json["devDependencies"]))
119
+ (dependencies + worskpace_dependencies).uniq
120
+ end
121
+
122
+ def build_workspaces(workspaces)
123
+ return [] if workspaces.nil?
124
+ workspaces.map do |workspace|
125
+ glob = "#{@root_path}/#{workspace}/package.json"
126
+ workspace_dependencies = Dir.glob(glob)
127
+ workspace_dependencies.map do |wd|
128
+ { name: component_name(wd), path: component_path(wd) }
129
+ end
130
+ end.flatten
131
+ end
132
+
133
+ private
134
+
135
+ def component_name(dir)
136
+ component_path(dir).split("/")[-1]
137
+ end
138
+
139
+ def component_path(dir)
140
+ return dir.split("/package.json")[0] if @root_path == "."
141
+
142
+ dir.split(@root_path)[-1].split("/package.json")[0]
143
+ end
144
+ end
145
+ end
146
+ end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "cobra_commander/component_tree"
4
3
  require "cobra_commander/affected"
5
4
  require "open3"
6
5
 
@@ -9,12 +8,12 @@ module CobraCommander
9
8
  class Change
10
9
  InvalidSelectionError = Class.new(StandardError)
11
10
 
12
- def initialize(path, results, branch)
13
- @root_dir = Dir.chdir(path) { `git rev-parse --show-toplevel`.chomp }
11
+ def initialize(tree, results, branch)
12
+ @root_dir = Dir.chdir(tree.path) { `git rev-parse --show-toplevel`.chomp }
14
13
  @results = results
15
14
  @branch = branch
16
- @tree = CobraCommander.umbrella_tree(path).to_h
17
- @affected = Affected.new(@tree, changes, path)
15
+ @tree = tree.to_h
16
+ @affected = Affected.new(@tree, changes, tree.path)
18
17
  end
19
18
 
20
19
  def run!
@@ -1,42 +1,55 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "thor"
4
+ require "fileutils"
4
5
 
5
6
  module CobraCommander
6
7
  # Implements the tool's CLI
7
8
  class CLI < Thor
8
- desc "do [command]", "Executes the command in the context of each component in [app]"
9
+ CACHE_DESCRIPTION = "Path to a cache file to use (default: nil). If specified, this file will be used to store " \
10
+ "the component tree for the app to speed up subsequent invocations. Must be rotated any time the component " \
11
+ "dependency structure changes."
12
+ COMMON_OPTIONS = "[--app=pwd] [--format=FORMAT] [--cache=nil]"
13
+
14
+ desc "do [command] [--app=pwd] [--cache=nil]", "Executes the command in the context of each component in [app]"
9
15
  method_option :app, default: Dir.pwd, aliases: "-a", desc: "App path (default: CWD)"
16
+ method_option :cache, default: nil, aliases: "-c", desc: CACHE_DESCRIPTION
10
17
  def do(command)
11
- tree = CobraCommander.umbrella_tree(options.app)
18
+ tree = maybe_cached_tree(options.app, options.cache)
12
19
  executor = Executor.new(tree)
13
20
  executor.exec(command)
14
21
  end
15
22
 
16
- desc "ls [app_path]", "Prints tree of components for an app"
23
+ desc "ls [app_path] #{COMMON_OPTIONS}", "Prints tree of components for an app"
17
24
  method_option :app, default: Dir.pwd, aliases: "-a", desc: "App path (default: CWD)"
18
25
  method_option :format, default: "tree", aliases: "-f", desc: "Format (list or tree, default: list)"
26
+ method_option :cache, default: nil, aliases: "-c", desc: CACHE_DESCRIPTION
19
27
  def ls(app_path = nil)
28
+ tree = maybe_cached_tree(app_path || options.app, options.cache)
20
29
  Output.print(
21
- CobraCommander.umbrella_tree(app_path || options.app),
30
+ tree,
22
31
  options.format
23
32
  )
24
33
  end
25
34
 
26
- desc "dependents_of [component]", "Outputs count of components in [app] dependent on [component]"
35
+ desc "dependents_of [component] #{COMMON_OPTIONS}", "Outputs count of components in [app] dependent on [component]"
27
36
  method_option :app, default: Dir.pwd, aliases: "-a", desc: "Path to the root app where the component is mounted"
28
37
  method_option :format, default: "count", aliases: "-f", desc: "count or list"
38
+ method_option :cache, default: nil, aliases: "-c", desc: CACHE_DESCRIPTION
29
39
  def dependents_of(component)
30
- dependents = CobraCommander.umbrella_tree(options.app).dependents_of(component)
40
+ tree = maybe_cached_tree(options.app, options.cache)
41
+ dependents = tree.dependents_of(component)
31
42
  puts "list" == options.format ? dependents.map(&:name) : dependents.size
32
43
  end
33
44
 
34
- desc "dependencies_of [component]", "Outputs a list of components that [component] depends on within [app] context"
45
+ desc "dependencies_of [component] #{COMMON_OPTIONS}", "Outputs a list of components that [component] depends on"
35
46
  method_option :app, default: Dir.pwd, aliases: "-a", desc: "App path (default: CWD)"
36
47
  method_option :format, default: "list", aliases: "-f", desc: "Format (list or tree, default: list)"
48
+ method_option :cache, default: nil, aliases: "-c", desc: CACHE_DESCRIPTION
37
49
  def dependencies_of(component)
50
+ tree = maybe_cached_tree(options.app, options.cache)
38
51
  Output.print(
39
- CobraCommander.umbrella_tree(options.app).subtree(component),
52
+ tree.subtree(component),
40
53
  options.format
41
54
  )
42
55
  end
@@ -46,17 +59,47 @@ module CobraCommander
46
59
  puts CobraCommander::VERSION
47
60
  end
48
61
 
49
- desc "graph APP_PATH [--format=FORMAT]", "Outputs graph"
62
+ desc "graph APP_PATH [--format=FORMAT] [--cache=nil]", "Outputs graph"
50
63
  method_option :format, default: "png", aliases: "-f", desc: "Accepts png or dot"
64
+ method_option :cache, default: nil, aliases: "-c", desc: CACHE_DESCRIPTION
51
65
  def graph(app_path)
52
- Graph.new(app_path, options.format).generate!
66
+ tree = maybe_cached_tree(app_path, options.cache)
67
+ Graph.new(tree, options.format).generate!
53
68
  end
54
69
 
55
- desc "changes APP_PATH [--results=RESULTS] [--branch=BRANCH]", "Prints list of changed files"
70
+ desc "changes APP_PATH [--results=RESULTS] [--branch=BRANCH] [--cache=nil]", "Prints list of changed files"
56
71
  method_option :results, default: "test", aliases: "-r", desc: "Accepts test, full, name or json"
57
72
  method_option :branch, default: "master", aliases: "-b", desc: "Specified target to calculate against"
73
+ method_option :cache, default: nil, aliases: "-c", desc: CACHE_DESCRIPTION
58
74
  def changes(app_path)
59
- Change.new(app_path, options.results, options.branch).run!
75
+ tree = maybe_cached_tree(app_path, options.cache)
76
+ Change.new(tree, options.results, options.branch).run!
77
+ end
78
+
79
+ desc "cache APP_PATH CACHE_PATH", "Caches a representation of the component structure of the app"
80
+ def cache(app_path, cache_path)
81
+ tree = CobraCommander.umbrella_tree(app_path)
82
+ write_tree_cache(tree, cache_path)
83
+ puts "Created cache of component tree at #{cache_path}"
84
+ end
85
+
86
+ private
87
+
88
+ def maybe_cached_tree(app_path, cache_path)
89
+ return CobraCommander.umbrella_tree(app_path) unless cache_path
90
+
91
+ if File.exist?(cache_path)
92
+ CobraCommander.tree_from_cache(cache_path)
93
+ else
94
+ tree = CobraCommander.umbrella_tree(app_path)
95
+ write_tree_cache(tree, cache_path)
96
+ tree
97
+ end
98
+ end
99
+
100
+ def write_tree_cache(tree, cache_path)
101
+ FileUtils.mkdir_p(File.dirname(cache_path))
102
+ File.write(cache_path, tree.to_json)
60
103
  end
61
104
  end
62
105
  end
@@ -8,13 +8,9 @@ module CobraCommander
8
8
  class ComponentTree
9
9
  attr_reader :name, :path
10
10
 
11
- def initialize(name, path, ancestry = Set.new)
11
+ def initialize(name, path)
12
12
  @name = name
13
13
  @path = path
14
- @ancestry = ancestry
15
- @ruby = Ruby.new(path)
16
- @js = Js.new(path)
17
- @type = type_of_component
18
14
  end
19
15
 
20
16
  def flatten
@@ -39,22 +35,18 @@ module CobraCommander
39
35
  [depends, dependents_below].flatten.compact.uniq(&:name)
40
36
  end
41
37
 
42
- def to_h
38
+ def to_h(json_compatible: false)
43
39
  {
44
40
  name: @name,
45
41
  path: path,
46
42
  type: @type,
47
- ancestry: @ancestry,
48
- dependencies: dependencies.map(&:to_h),
43
+ ancestry: json_compatible ? @ancestry.to_a : @ancestry,
44
+ dependencies: dependencies.map { |dep| dep.to_h(json_compatible: json_compatible) },
49
45
  }
50
46
  end
51
47
 
52
- def dependencies
53
- @deps ||= begin
54
- deps = @ruby.dependencies + @js.dependencies
55
- deps.sort_by { |dep| dep[:name] }
56
- .map(&method(:dep_representation))
57
- end
48
+ def to_json
49
+ JSON.dump(to_h(json_compatible: true))
58
50
  end
59
51
 
60
52
  private
@@ -73,98 +65,5 @@ module CobraCommander
73
65
  end
74
66
  nil
75
67
  end
76
-
77
- def type_of_component
78
- return "Ruby & JS" if @ruby.gem? && @js.node?
79
- return "Ruby" if @ruby.gem?
80
- return "JS" if @js.node?
81
- end
82
-
83
- def dep_representation(dep)
84
- full_path = File.expand_path(File.join(path, dep[:path]))
85
- ancestry = @ancestry + [{ name: @name, path: path, type: @type }]
86
- ComponentTree.new(dep[:name], full_path, ancestry)
87
- end
88
-
89
- # Calculates ruby dependencies
90
- class Ruby
91
- def initialize(root_path)
92
- @root_path = root_path
93
- end
94
-
95
- def dependencies
96
- @deps ||= begin
97
- return [] unless gem?
98
- gems = bundler_definition.dependencies.select { |dep| path?(dep.source) }
99
- format(gems)
100
- end
101
- end
102
-
103
- def path?(source)
104
- return if source.nil?
105
- source_has_path = source.respond_to?(:path?) ? source.path? : source.is_a_path?
106
- source_has_path && source.path.to_s != "."
107
- end
108
-
109
- def format(deps)
110
- deps.map do |dep|
111
- path = File.join(dep.source.path, dep.name)
112
- { name: dep.name, path: path }
113
- end
114
- end
115
-
116
- def gem?
117
- @gem ||= File.exist?(gemfile_path)
118
- end
119
-
120
- def bundler_definition
121
- ::Bundler::Definition.build(gemfile_path, gemfile_lock_path, nil)
122
- end
123
-
124
- def gemfile_path
125
- File.join(@root_path, "Gemfile")
126
- end
127
-
128
- def gemfile_lock_path
129
- File.join(@root_path, "Gemfile.lock")
130
- end
131
- end
132
-
133
- # Calculates js dependencies
134
- class Js
135
- def initialize(root_path)
136
- @root_path = root_path
137
- end
138
-
139
- def dependencies
140
- @deps ||= begin
141
- return [] unless node?
142
- json = JSON.parse(File.read(package_json_path))
143
- format combined_deps(json)
144
- end
145
- end
146
-
147
- def format(deps)
148
- return [] if deps.nil?
149
- linked_deps = deps.select { |_, v| v.start_with? "link:" }
150
- linked_deps.map do |_, v|
151
- relational_path = v.split("link:")[1]
152
- dep_name = relational_path.split("/")[-1]
153
- { name: dep_name, path: relational_path }
154
- end
155
- end
156
-
157
- def node?
158
- @node ||= File.exist?(package_json_path)
159
- end
160
-
161
- def package_json_path
162
- File.join(@root_path, "package.json")
163
- end
164
-
165
- def combined_deps(json)
166
- Hash(json["dependencies"]).merge(Hash(json["devDependencies"]))
167
- end
168
- end
169
68
  end
170
69
  end
@@ -1,14 +1,13 @@
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(tree, format)
10
9
  @format = format
11
- @tree = CobraCommander.umbrella_tree(app_path).to_h
10
+ @tree = tree.to_h
12
11
  end
13
12
 
14
13
  def generate!
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CobraCommander
4
- VERSION = "0.5.1"
4
+ VERSION = "0.6.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cobra_commander
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Langfeld
@@ -9,28 +9,28 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2018-10-16 00:00:00.000000000 Z
12
+ date: 2019-07-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - "<"
19
- - !ruby/object:Gem::Version
20
- version: '2.0'
21
18
  - - ">="
22
19
  - !ruby/object:Gem::Version
23
20
  version: 0.18.1
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: '2.0'
24
24
  type: :runtime
25
25
  prerelease: false
26
26
  version_requirements: !ruby/object:Gem::Requirement
27
27
  requirements:
28
- - - "<"
29
- - !ruby/object:Gem::Version
30
- version: '2.0'
31
28
  - - ">="
32
29
  - !ruby/object:Gem::Version
33
30
  version: 0.18.1
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
34
  - !ruby/object:Gem::Dependency
35
35
  name: ruby-graphviz
36
36
  requirement: !ruby/object:Gem::Requirement
@@ -173,6 +173,8 @@ files:
173
173
  - exe/cobra
174
174
  - lib/cobra_commander.rb
175
175
  - lib/cobra_commander/affected.rb
176
+ - lib/cobra_commander/cached_component_tree.rb
177
+ - lib/cobra_commander/calculated_component_tree.rb
176
178
  - lib/cobra_commander/change.rb
177
179
  - lib/cobra_commander/cli.rb
178
180
  - lib/cobra_commander/component_tree.rb
@@ -199,8 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
199
201
  - !ruby/object:Gem::Version
200
202
  version: '0'
201
203
  requirements: []
202
- rubyforge_project:
203
- rubygems_version: 2.7.3
204
+ rubygems_version: 3.0.4
204
205
  signing_key:
205
206
  specification_version: 4
206
207
  summary: Tools for working with Component Based Rails Apps