cobra_commander 0.5.1 → 0.6.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.
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