Class: Jsus::Container
- Inherits:
-
Object
- Object
- Jsus::Container
- Defined in:
- lib/jsus/container.rb
Overview
Container is an array that contains source files. Main difference from an array is the fact that container maintains topological sort for the source files.
This class is mostly used internally.
Constant Summary collapse
- CACHE_CLEAR_METHODS =
List of methods that clear cached state of container when called.
[ "map!", "reject!", "inject!", "collect!", "delete", "delete_at" ]
- DELEGATED_METHODS =
List of methods that are delegated to underlying array of sources.
[ "==", "to_a", "map", "map!", "each", "inject", "inject!", "collect", "collect!", "reject", "reject!", "detect", "size", "length", "[]", "empty?", "index", "include?", "select", "delete_if", "delete", "-", "+", "|", "&" ]
Instance Method Summary collapse
-
#clear_cache! ⇒ Object
private
Clears all caches for given container.
-
#dependency_cache ⇒ Hash
private
Cached map of dependencies pointing to source files.
-
#flatten ⇒ Array
Flattens the container items.
-
#initialize(*sources) ⇒ Container
constructor
Instantiates a container from given sources.
-
#inspect ⇒ Object
Shows inspection of the container.
- #output_cycles(graph) ⇒ Object private
-
#provides_tree ⇒ Jsus::Util::Tree
private
Cached tree of what source files provide.
-
#provides_tree! ⇒ Jsus::Util::Tree
private
Returns tree of what source files provide.
-
#push(source) ⇒ Object
(also: #<<)
Pushes an item to the container.
-
#remove_replaced_files! ⇒ Object
private
Removes files which are marked as replaced by other sources.
-
#replacements_tree ⇒ Jsus::Util::Tree
private
Cached tree of what source files replace.
-
#replacements_tree! ⇒ Jsus::Util::Tree
private
Returns tree of what source files replace.
-
#required_files(root = nil) ⇒ Array
Lists all the required files (dependencies and extensions) for the sources in the container.
-
#sort! ⇒ self
Topologically sorts items in container if required.
-
#sorted? ⇒ Boolean
Returns whether container requires sorting.
-
#sources ⇒ Array
(also: #to_a)
Contains the source files.
-
#sources=(new_value) ⇒ Object
Sets sources to new value.
-
#topsort ⇒ Object
private
Performs topological sort inside current container.
Constructor Details
#initialize(*sources) ⇒ Container
Instantiates a container from given sources.
13 14 15 16 17 |
# File 'lib/jsus/container.rb', line 13 def initialize(*sources) sources.each do |source| push(source) end end |
Instance Method Details
#clear_cache! ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Clears all caches for given container.
228 229 230 231 232 233 |
# File 'lib/jsus/container.rb', line 228 def clear_cache! @provides_tree = nil @replacements_tree = nil @dependency_cache = nil @sorted = false end |
#dependency_cache ⇒ Hash
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Cached map of dependencies pointing to source files.
161 162 163 |
# File 'lib/jsus/container.rb', line 161 def dependency_cache @dependency_cache ||= {} end |
#flatten ⇒ Array
Flattens the container items
40 41 42 |
# File 'lib/jsus/container.rb', line 40 def flatten map {|item| item.respond_to?(:flatten) ? item.flatten : item }.flatten end |
#inspect ⇒ Object
Shows inspection of the container.
105 106 107 |
# File 'lib/jsus/container.rb', line 105 def inspect "#<#{self.class.name}:#{self.object_id} #{self.sources.inspect}>" end |
#output_cycles(graph) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/jsus/container.rb', line 141 def output_cycles(graph) cycles = graph.cycles error_msg = [] unless cycles.empty? error_msg << "Jsus has discovered you have circular dependencies in your code." error_msg << "Please resolve them immediately!" error_msg << "List of circular dependencies:" cycles.each do |cycle| error_msg << "-" * 30 error_msg << (cycle + [cycle.first]).map {|sf| sf.filename}.join(" => ") end error_msg << "-" * 30 error_msg = error_msg.join("\n") Jsus.logger.fatal(error_msg) end end |
#provides_tree ⇒ Jsus::Util::Tree
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Cached tree of what source files provide.
169 170 171 |
# File 'lib/jsus/container.rb', line 169 def provides_tree @provides_tree ||= provides_tree! end |
#provides_tree! ⇒ Jsus::Util::Tree
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns tree of what source files provide.
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/jsus/container.rb', line 177 def provides_tree! tree = Util::Tree.new # Provisions sources.each do |file| file.provides.each do |tag| tree[tag] = file end end # Replacements sources.each do |file| if file.replaces tree[file.replaces] = file end end tree end |
#push(source) ⇒ Object Also known as: <<
Pushes an item to the container
24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/jsus/container.rb', line 24 def push(source) if source if source.kind_of?(Array) || source.kind_of?(Container) source.each {|s| self.push(s) } else sources.push(source) unless sources.include?(source) end end clear_cache! self end |
#remove_replaced_files! ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Removes files which are marked as replaced by other sources.
197 198 199 200 201 |
# File 'lib/jsus/container.rb', line 197 def remove_replaced_files! sources.reject! do |sf| !sf.provides.empty? && sf.provides.any? { |tag| replacements_tree[tag] && replacements_tree[tag] != sf } end end |
#replacements_tree ⇒ Jsus::Util::Tree
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Cached tree of what source files replace.
207 208 209 |
# File 'lib/jsus/container.rb', line 207 def replacements_tree @replacements_tree ||= replacements_tree! end |
#replacements_tree! ⇒ Jsus::Util::Tree
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns tree of what source files replace.
215 216 217 218 219 220 221 222 223 |
# File 'lib/jsus/container.rb', line 215 def replacements_tree! tree = Util::Tree.new sources.each do |file| if file.replaces tree[file.replaces] = file end end tree end |
#required_files(root = nil) ⇒ Array
Lists all the required files (dependencies and extensions) for the sources in the container. Consider it a projection from source files space onto filesystem space.
Optionally accepts a filesystem point to calculate relative paths from.
93 94 95 96 97 98 99 100 101 |
# File 'lib/jsus/container.rb', line 93 def required_files(root = nil) sort! files = sources.map {|s| s.required_files }.flatten if root root = Pathname.new(File.(root)) files = files.map {|f| Pathname.new(File.(f)).relative_path_from(root).to_s } end files end |
#sort! ⇒ self
Topologically sorts items in container if required.
66 67 68 69 70 71 72 73 |
# File 'lib/jsus/container.rb', line 66 def sort! unless sorted? remove_replaced_files! self.sources = topsort @sorted = true end self end |
#sorted? ⇒ Boolean
Returns whether container requires sorting.
79 80 81 |
# File 'lib/jsus/container.rb', line 79 def sorted? !!@sorted end |
#sources ⇒ Array Also known as: to_a
Contains the source files. Please, don't use sources directly, if you depend on them to be topologically sorted. Use collection methods like inject/reject/map directly on the container instead.
50 51 52 |
# File 'lib/jsus/container.rb', line 50 def sources @sources ||= [] end |
#sources=(new_value) ⇒ Object
Sets sources to new value.
58 59 60 |
# File 'lib/jsus/container.rb', line 58 def sources=(new_value) # :nodoc: @sources = new_value end |
#topsort ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Performs topological sort inside current container.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/jsus/container.rb', line 114 def topsort graph = RGL::DirectedAdjacencyGraph.new # init vertices items = sources items.each {|item| graph.add_vertex(item) } # init edges items.each do |item| item.dependencies.each do |dependency| # If we can find items that provide the required dependency... # (dependency could be a wildcard as well, hence items) dependency_cache[dependency] ||= provides_tree.glob(dependency) # ... we draw an edge from every required item to the dependant item dependency_cache[dependency].each do |required_item| graph.add_edge(required_item, item) end end end begin graph.topsorted_vertices rescue RGL::TopsortedGraphHasCycles => e output_cycles(graph) raise e # fail fast end end |