nanoc 4.11.8 → 4.11.9

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/NEWS.md +8 -0
  3. data/lib/nanoc.rb +4 -1
  4. data/lib/nanoc/base.rb +0 -1
  5. data/lib/nanoc/base/errors.rb +4 -49
  6. data/lib/nanoc/base/repos.rb +0 -15
  7. data/lib/nanoc/base/repos/site_loader.rb +1 -1
  8. data/lib/nanoc/base/services.rb +0 -2
  9. data/lib/nanoc/base/services/compiler.rb +1 -1
  10. data/lib/nanoc/base/services/compiler/phases/recalculate.rb +1 -1
  11. data/lib/nanoc/base/services/compiler/stages/build_reps.rb +1 -1
  12. data/lib/nanoc/base/services/compiler/stages/cleanup.rb +1 -1
  13. data/lib/nanoc/base/services/compiler/stages/load_stores.rb +1 -1
  14. data/lib/nanoc/base/services/compiler_loader.rb +6 -6
  15. data/lib/nanoc/base/services/outdatedness_checker.rb +10 -10
  16. data/lib/nanoc/base/services/outdatedness_rules/attributes_modified.rb +4 -4
  17. data/lib/nanoc/base/services/outdatedness_rules/code_snippets_modified.rb +2 -2
  18. data/lib/nanoc/base/services/outdatedness_rules/content_modified.rb +2 -2
  19. data/lib/nanoc/base/services/outdatedness_rules/item_collection_extended.rb +3 -3
  20. data/lib/nanoc/base/services/outdatedness_rules/layout_collection_extended.rb +3 -3
  21. data/lib/nanoc/base/services/outdatedness_rules/not_written.rb +2 -2
  22. data/lib/nanoc/base/services/outdatedness_rules/rules_modified.rb +3 -3
  23. data/lib/nanoc/base/services/outdatedness_rules/uses_always_outdated_filter.rb +2 -2
  24. data/lib/nanoc/base/services/pruner.rb +1 -1
  25. data/lib/nanoc/base/views/view_context_for_compilation.rb +1 -1
  26. data/lib/nanoc/base/views/view_context_for_pre_compilation.rb +1 -1
  27. data/lib/nanoc/base/views/view_context_for_shell.rb +2 -2
  28. data/lib/nanoc/checking/check.rb +17 -1
  29. data/lib/nanoc/cli/commands/shell.rb +1 -1
  30. data/lib/nanoc/cli/error_handler.rb +1 -1
  31. data/lib/nanoc/filters/handlebars.rb +2 -2
  32. data/lib/nanoc/filters/sass/importer.rb +3 -2
  33. data/lib/nanoc/rule_dsl/action_provider.rb +1 -1
  34. data/lib/nanoc/spec.rb +4 -4
  35. data/lib/nanoc/version.rb +1 -1
  36. metadata +5 -21
  37. data/lib/nanoc/base/entities.rb +0 -7
  38. data/lib/nanoc/base/entities/outdatedness_reasons.rb +0 -88
  39. data/lib/nanoc/base/entities/outdatedness_status.rb +0 -27
  40. data/lib/nanoc/base/repos/action_sequence_store.rb +0 -50
  41. data/lib/nanoc/base/repos/binary_compiled_content_cache.rb +0 -128
  42. data/lib/nanoc/base/repos/checksum_store.rb +0 -74
  43. data/lib/nanoc/base/repos/compiled_content_cache.rb +0 -68
  44. data/lib/nanoc/base/repos/compiled_content_store.rb +0 -77
  45. data/lib/nanoc/base/repos/dependency_store.rb +0 -204
  46. data/lib/nanoc/base/repos/item_rep_repo.rb +0 -37
  47. data/lib/nanoc/base/repos/outdatedness_store.rb +0 -55
  48. data/lib/nanoc/base/repos/prefixed_data_source.rb +0 -31
  49. data/lib/nanoc/base/repos/store.rb +0 -114
  50. data/lib/nanoc/base/repos/textual_compiled_content_cache.rb +0 -82
  51. data/lib/nanoc/base/services/dependency_tracker.rb +0 -63
  52. data/lib/nanoc/base/services/outdatedness_rule.rb +0 -34
@@ -1,128 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc
4
- module Int
5
- # Represents a cache than can be used to store already compiled content,
6
- # to prevent it from being needlessly recompiled.
7
- #
8
- # @api private
9
- class BinaryCompiledContentCache < ::Nanoc::Int::Store
10
- include Nanoc::Core::ContractsSupport
11
-
12
- contract C::KeywordArgs[config: Nanoc::Core::Configuration] => C::Any
13
- def initialize(config:)
14
- super(Nanoc::Int::Store.tmp_path_for(config: config, store_name: 'binary_content'), 1)
15
-
16
- @cache = {}
17
- end
18
-
19
- contract Nanoc::Core::ItemRep => C::Maybe[C::HashOf[Symbol => Nanoc::Core::Content]]
20
- # Returns the cached compiled content for the given item representation.
21
- #
22
- # This cached compiled content is a hash where the keys are the snapshot
23
- # names, and the values the compiled content at the given snapshot.
24
- def [](rep)
25
- item_cache = @cache[rep.item.identifier] || {}
26
-
27
- rep_cache = item_cache[rep.name]
28
- return nil if rep_cache.nil?
29
-
30
- rep_cache.transform_values do |filename|
31
- Nanoc::Core::Content.create(filename, binary: true)
32
- end
33
- end
34
-
35
- contract Nanoc::Core::ItemRep => C::Bool
36
- def include?(rep)
37
- item_cache = @cache[rep.item.identifier] || {}
38
- item_cache.key?(rep.name)
39
- end
40
-
41
- contract Nanoc::Core::ItemRep, C::HashOf[Symbol => Nanoc::Core::BinaryContent] => C::HashOf[Symbol => Nanoc::Core::Content]
42
- # Sets the compiled content for the given representation.
43
- #
44
- # This cached compiled content is a hash where the keys are the snapshot
45
- # names, and the values the compiled content at the given snapshot.
46
- def []=(rep, content)
47
- @cache[rep.item.identifier] ||= {}
48
- @cache[rep.item.identifier][rep.name] ||= {}
49
- rep_cache = @cache[rep.item.identifier][rep.name]
50
-
51
- content.each do |snapshot, binary_content|
52
- filename = build_filename(rep, snapshot)
53
- rep_cache[snapshot] = filename
54
-
55
- # Avoid reassigning the same content if this binary cached content was
56
- # already used, because it was available and the item wasn’t oudated.
57
- next if binary_content.filename == filename
58
-
59
- # Copy
60
- #
61
- # NOTE: hardlinking is not an option in this case, because hardlinking
62
- # would make it possible for the content to be (inadvertently)
63
- # changed outside of Nanoc.
64
- FileUtils.mkdir_p(File.dirname(filename))
65
- FileUtils.cp(binary_content.filename, filename)
66
- end
67
- end
68
-
69
- def prune(items:)
70
- item_identifiers = Set.new(items.map(&:identifier))
71
-
72
- @cache.each_key do |key|
73
- # TODO: remove unused item reps
74
- next if item_identifiers.include?(key)
75
-
76
- @cache.delete(key)
77
- path = dirname_for_item_identifier(key)
78
- FileUtils.rm_rf(path)
79
- end
80
- end
81
-
82
- def data
83
- @cache
84
- end
85
-
86
- def data=(new_data)
87
- @cache = {}
88
-
89
- new_data.each_pair do |item_identifier, content_per_rep|
90
- @cache[item_identifier] ||= content_per_rep
91
- end
92
- end
93
-
94
- private
95
-
96
- def dirname
97
- filename + '_data'
98
- end
99
-
100
- def string_to_path_component(string)
101
- string.gsub(/[^a-zA-Z0-9]+/, '_') +
102
- '-' +
103
- Digest::SHA1.hexdigest(string)[0..9]
104
- end
105
-
106
- def dirname_for_item_identifier(item_identifier)
107
- File.join(
108
- dirname,
109
- string_to_path_component(item_identifier.to_s),
110
- )
111
- end
112
-
113
- def dirname_for_item_rep(rep)
114
- File.join(
115
- dirname_for_item_identifier(rep.item.identifier),
116
- string_to_path_component(rep.name.to_s),
117
- )
118
- end
119
-
120
- def build_filename(rep, snapshot_name)
121
- File.join(
122
- dirname_for_item_rep(rep),
123
- string_to_path_component(snapshot_name.to_s),
124
- )
125
- end
126
- end
127
- end
128
- end
@@ -1,74 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc
4
- module Int
5
- # Stores checksums for objects in order to be able to detect whether a file
6
- # has changed since the last site compilation.
7
- #
8
- # @api private
9
- class ChecksumStore < ::Nanoc::Int::Store
10
- include Nanoc::Core::ContractsSupport
11
-
12
- attr_writer :checksums
13
- attr_accessor :objects
14
-
15
- c_obj = C::Or[Nanoc::Core::Item, Nanoc::Core::Layout, Nanoc::Core::Configuration, Nanoc::Core::CodeSnippet]
16
-
17
- contract C::KeywordArgs[config: Nanoc::Core::Configuration, objects: C::IterOf[c_obj]] => C::Any
18
- def initialize(config:, objects:)
19
- super(Nanoc::Int::Store.tmp_path_for(config: config, store_name: 'checksums'), 2)
20
-
21
- @objects = objects
22
-
23
- @checksums = {}
24
- end
25
-
26
- contract c_obj => C::Maybe[String]
27
- def [](obj)
28
- @checksums[obj.reference]
29
- end
30
-
31
- contract c_obj => self
32
- def add(obj)
33
- if obj.is_a?(Nanoc::Core::Document)
34
- @checksums[[obj.reference, :content]] = Nanoc::Core::Checksummer.calc_for_content_of(obj)
35
- end
36
-
37
- if obj.is_a?(Nanoc::Core::Document) || obj.is_a?(Nanoc::Core::Configuration)
38
- @checksums[[obj.reference, :each_attribute]] = Nanoc::Core::Checksummer.calc_for_each_attribute_of(obj)
39
- end
40
-
41
- @checksums[obj.reference] = Nanoc::Core::Checksummer.calc(obj)
42
-
43
- self
44
- end
45
-
46
- contract c_obj => C::Maybe[String]
47
- def content_checksum_for(obj)
48
- @checksums[[obj.reference, :content]]
49
- end
50
-
51
- contract c_obj => C::Maybe[C::HashOf[Symbol, String]]
52
- def attributes_checksum_for(obj)
53
- @checksums[[obj.reference, :each_attribute]]
54
- end
55
-
56
- protected
57
-
58
- def data
59
- @checksums
60
- end
61
-
62
- def data=(new_data)
63
- references = Set.new(@objects.map(&:reference))
64
-
65
- @checksums = {}
66
- new_data.each_pair do |key, checksum|
67
- if references.include?(key) || references.include?(key.first)
68
- @checksums[key] = checksum
69
- end
70
- end
71
- end
72
- end
73
- end
74
- end
@@ -1,68 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc
4
- module Int
5
- # Represents a cache than can be used to store already compiled content,
6
- # to prevent it from being needlessly recompiled.
7
- #
8
- # @api private
9
- class CompiledContentCache < ::Nanoc::Int::Store
10
- include Nanoc::Core::ContractsSupport
11
-
12
- contract C::KeywordArgs[config: Nanoc::Core::Configuration] => C::Any
13
- def initialize(config:)
14
- @textual_cache = Nanoc::Int::TextualCompiledContentCache.new(config: config)
15
- @binary_cache = Nanoc::Int::BinaryCompiledContentCache.new(config: config)
16
-
17
- @wrapped_caches = [@textual_cache, @binary_cache]
18
- end
19
-
20
- contract Nanoc::Core::ItemRep => C::Maybe[C::HashOf[Symbol => Nanoc::Core::Content]]
21
- # Returns the cached compiled content for the given item representation.
22
- #
23
- # This cached compiled content is a hash where the keys are the snapshot
24
- # names. and the values the compiled content at the given snapshot.
25
- def [](rep)
26
- textual_content_map = @textual_cache[rep]
27
- binary_content_map = @binary_cache[rep]
28
-
29
- # If either the textual or the binary content cache is nil, assume the
30
- # cache is entirely absent.
31
- #
32
- # This is necessary to support the case where only textual content is
33
- # cached (which was the case in older versions of Nanoc).
34
- return nil if [textual_content_map, binary_content_map].any?(&:nil?)
35
-
36
- textual_content_map.merge(binary_content_map)
37
- end
38
-
39
- contract Nanoc::Core::ItemRep, C::HashOf[Symbol => Nanoc::Core::Content] => C::Any
40
- # Sets the compiled content for the given representation.
41
- #
42
- # This cached compiled content is a hash where the keys are the snapshot
43
- # names and the values the compiled content at the given snapshot.
44
- def []=(rep, content)
45
- @textual_cache[rep] = content.select { |_key, c| c.textual? }
46
- @binary_cache[rep] = content.select { |_key, c| c.binary? }
47
- end
48
-
49
- def prune(*args)
50
- @wrapped_caches.each { |w| w.prune(*args) }
51
- end
52
-
53
- # True if there is cached compiled content available for this item, and
54
- # all entries are present (either textual or binary).
55
- def full_cache_available?(rep)
56
- @textual_cache.include?(rep) && @binary_cache.include?(rep)
57
- end
58
-
59
- def load(*args)
60
- @wrapped_caches.each { |w| w.load(*args) }
61
- end
62
-
63
- def store(*args)
64
- @wrapped_caches.each { |w| w.store(*args) }
65
- end
66
- end
67
- end
68
- end
@@ -1,77 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc
4
- module Int
5
- # @api private
6
- class CompiledContentStore
7
- include Nanoc::Core::ContractsSupport
8
-
9
- def initialize
10
- @contents = Hash.new { |hash, rep| hash[rep] = {} }
11
- @current_content = {}
12
- end
13
-
14
- contract Nanoc::Core::ItemRep, Symbol => C::Maybe[Nanoc::Core::Content]
15
- def get(rep, snapshot_name)
16
- @contents[rep][snapshot_name]
17
- end
18
-
19
- contract Nanoc::Core::ItemRep => C::Maybe[Nanoc::Core::Content]
20
- def get_current(rep)
21
- @current_content[rep]
22
- end
23
-
24
- contract Nanoc::Core::ItemRep, Symbol, Nanoc::Core::Content => C::Any
25
- def set(rep, snapshot_name, contents)
26
- @contents[rep][snapshot_name] = contents
27
- end
28
-
29
- contract Nanoc::Core::ItemRep, Nanoc::Core::Content => C::Any
30
- def set_current(rep, content)
31
- @current_content[rep] = content
32
- end
33
-
34
- contract Nanoc::Core::ItemRep => C::HashOf[Symbol => Nanoc::Core::Content]
35
- def get_all(rep)
36
- @contents[rep]
37
- end
38
-
39
- contract Nanoc::Core::ItemRep, C::HashOf[Symbol => Nanoc::Core::Content] => C::Any
40
- def set_all(rep, contents_per_snapshot)
41
- @contents[rep] = contents_per_snapshot
42
- end
43
-
44
- contract C::KeywordArgs[rep: Nanoc::Core::ItemRep, snapshot: C::Optional[C::Maybe[Symbol]]] => Nanoc::Core::Content
45
- def raw_compiled_content(rep:, snapshot: nil)
46
- # Get name of last pre-layout snapshot
47
- has_pre = rep.snapshot_defs.any? { |sd| sd.name == :pre }
48
- snapshot_name = snapshot || (has_pre ? :pre : :last)
49
-
50
- # Check existance of snapshot
51
- snapshot_def = rep.snapshot_defs.reverse.find { |sd| sd.name == snapshot_name }
52
- unless snapshot_def
53
- raise Nanoc::Int::Errors::NoSuchSnapshot.new(rep, snapshot_name)
54
- end
55
-
56
- # Return content if it is available
57
- content = get(rep, snapshot_name)
58
- return content if content
59
-
60
- # Content is unavailable; notify and try again
61
- Fiber.yield(Nanoc::Int::Errors::UnmetDependency.new(rep, snapshot_name))
62
- get(rep, snapshot_name)
63
- end
64
-
65
- contract C::KeywordArgs[rep: Nanoc::Core::ItemRep, snapshot: C::Optional[C::Maybe[Symbol]]] => String
66
- def compiled_content(rep:, snapshot: nil)
67
- snapshot_content = raw_compiled_content(rep: rep, snapshot: snapshot)
68
-
69
- if snapshot_content.binary?
70
- raise Nanoc::Int::Errors::CannotGetCompiledContentOfBinaryItem.new(rep)
71
- end
72
-
73
- snapshot_content.string
74
- end
75
- end
76
- end
77
- end
@@ -1,204 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc
4
- module Int
5
- # @api private
6
- class DependencyStore < ::Nanoc::Int::Store
7
- include Nanoc::Core::ContractsSupport
8
-
9
- attr_reader :items
10
- attr_reader :layouts
11
-
12
- contract Nanoc::Core::ItemCollection, Nanoc::Core::LayoutCollection, Nanoc::Core::Configuration => C::Any
13
- def initialize(items, layouts, config)
14
- super(Nanoc::Int::Store.tmp_path_for(config: config, store_name: 'dependencies'), 5)
15
-
16
- @items = items
17
- @layouts = layouts
18
-
19
- @refs2objs = {}
20
- items.each { |o| add_vertex_for(o) }
21
- layouts.each { |o| add_vertex_for(o) }
22
- add_vertex_for(config)
23
- add_vertex_for(items)
24
- add_vertex_for(layouts)
25
-
26
- @new_objects = []
27
- @graph = Nanoc::Core::DirectedGraph.new([nil] + objs2refs(@items) + objs2refs(@layouts))
28
- end
29
-
30
- C_OBJ_SRC = Nanoc::Core::Item
31
- C_OBJ_DST = C::Or[Nanoc::Core::Item, Nanoc::Core::Layout, Nanoc::Core::Configuration, Nanoc::Core::IdentifiableCollection]
32
-
33
- contract C_OBJ_SRC => C::ArrayOf[Nanoc::Core::Dependency]
34
- def dependencies_causing_outdatedness_of(object)
35
- objects_causing_outdatedness_of(object).map do |other_object|
36
- props = props_for(other_object, object)
37
-
38
- Nanoc::Core::Dependency.new(
39
- other_object,
40
- object,
41
- Nanoc::Core::DependencyProps.new(
42
- raw_content: props.fetch(:raw_content, false),
43
- attributes: props.fetch(:attributes, false),
44
- compiled_content: props.fetch(:compiled_content, false),
45
- path: props.fetch(:path, false),
46
- ),
47
- )
48
- end
49
- end
50
-
51
- def items=(items)
52
- @items = items
53
- items.each { |o| @refs2objs[obj2ref(o)] = o }
54
- add_vertex_for(items)
55
- end
56
-
57
- def layouts=(layouts)
58
- @layouts = layouts
59
- layouts.each { |o| @refs2objs[obj2ref(o)] = o }
60
- add_vertex_for(layouts)
61
- end
62
-
63
- def new_items
64
- @new_objects.select { |o| o.is_a?(Nanoc::Core::Item) }
65
- end
66
-
67
- def new_layouts
68
- @new_objects.select { |o| o.is_a?(Nanoc::Core::Layout) }
69
- end
70
-
71
- # Returns the direct dependencies for the given object.
72
- #
73
- # The direct dependencies of the given object include the items and
74
- # layouts that, when outdated will cause the given object to be marked as
75
- # outdated. Indirect dependencies will not be returned (e.g. if A depends
76
- # on B which depends on C, then the direct dependencies of A do not
77
- # include C).
78
- #
79
- # The direct predecessors can include nil, which indicates an item that is
80
- # no longer present in the site.
81
- #
82
- # @param [Nanoc::Core::Item, Nanoc::Core::Layout] object The object for
83
- # which to fetch the direct predecessors
84
- #
85
- # @return [Array<Nanoc::Core::Item, Nanoc::Core::Layout, nil>] The direct
86
- # predecessors of
87
- # the given object
88
- def objects_causing_outdatedness_of(object)
89
- refs2objs(@graph.direct_predecessors_of(obj2ref(object)))
90
- end
91
-
92
- C_RAW_CONTENT = C::Or[C::IterOf[C::Or[String, Regexp]], C::Bool]
93
- C_ATTR = C::Or[C::IterOf[Symbol], C::Bool]
94
- C_KEYWORD_PROPS = C::KeywordArgs[raw_content: C::Optional[C_RAW_CONTENT], attributes: C::Optional[C_ATTR], compiled_content: C::Optional[C::Bool], path: C::Optional[C::Bool]]
95
-
96
- contract C::Maybe[C_OBJ_SRC], C::Maybe[C_OBJ_DST], C_KEYWORD_PROPS => C::Any
97
- # Records a dependency from `src` to `dst` in the dependency graph. When
98
- # `dst` is oudated, `src` will also become outdated.
99
- #
100
- # @param [Nanoc::Core::Item, Nanoc::Core::Layout] src The source of the dependency,
101
- # i.e. the object that will become outdated if dst is outdated
102
- #
103
- # @param [Nanoc::Core::Item, Nanoc::Core::Layout] dst The destination of the
104
- # dependency, i.e. the object that will cause the source to become
105
- # outdated if the destination is outdated
106
- #
107
- # @return [void]
108
- def record_dependency(src, dst, raw_content: false, attributes: false, compiled_content: false, path: false)
109
- return if src == dst
110
-
111
- add_vertex_for(src)
112
- add_vertex_for(dst)
113
-
114
- src_ref = obj2ref(src)
115
- dst_ref = obj2ref(dst)
116
-
117
- existing_props = Nanoc::Core::DependencyProps.new(@graph.props_for(dst_ref, src_ref) || {})
118
- new_props = Nanoc::Core::DependencyProps.new(raw_content: raw_content, attributes: attributes, compiled_content: compiled_content, path: path)
119
- props = existing_props.merge(new_props)
120
-
121
- @graph.add_edge(dst_ref, src_ref, props: props.to_h)
122
- end
123
-
124
- def add_vertex_for(obj)
125
- @refs2objs[obj2ref(obj)] = obj
126
- end
127
-
128
- # Empties the list of dependencies for the given object. This is necessary
129
- # before recompiling the given object, because otherwise old dependencies
130
- # will stick around and new dependencies will appear twice. This function
131
- # removes all incoming edges for the given vertex.
132
- #
133
- # @param [Nanoc::Core::Item, Nanoc::Core::Layout] object The object for which to
134
- # forget all dependencies
135
- #
136
- # @return [void]
137
- def forget_dependencies_for(object)
138
- @graph.delete_edges_to(obj2ref(object))
139
- end
140
-
141
- protected
142
-
143
- def obj2ref(obj)
144
- obj&.reference
145
- end
146
-
147
- def ref2obj(reference)
148
- if reference
149
- @refs2objs[reference]
150
- else
151
- nil
152
- end
153
- end
154
-
155
- def objs2refs(objs)
156
- objs.map { |o| obj2ref(o) }
157
- end
158
-
159
- def refs2objs(refs)
160
- refs.map { |r| ref2obj(r) }
161
- end
162
-
163
- def props_for(from, to)
164
- props = @graph.props_for(obj2ref(from), obj2ref(to)) || {}
165
-
166
- if props.values.any? { |v| v }
167
- props
168
- else
169
- { raw_content: true, attributes: true, compiled_content: true, path: true }
170
- end
171
- end
172
-
173
- def data
174
- {
175
- edges: @graph.edges,
176
- vertices: @graph.vertices,
177
- }
178
- end
179
-
180
- def data=(new_data)
181
- objects = Set.new(@items.to_a + @layouts.to_a)
182
- refs = objs2refs(objects)
183
-
184
- # Create new graph
185
- @graph = Nanoc::Core::DirectedGraph.new([nil] + refs)
186
-
187
- # Load vertices
188
- previous_refs = new_data[:vertices]
189
- previous_objects = Set.new(refs2objs(previous_refs))
190
-
191
- # Load edges
192
- new_data[:edges].each do |edge|
193
- from_index, to_index, props = *edge
194
- from = from_index && previous_refs[from_index]
195
- to = to_index && previous_refs[to_index]
196
- @graph.add_edge(from, to, props: props)
197
- end
198
-
199
- # Record dependency from all items on new items
200
- @new_objects = objects - previous_objects
201
- end
202
- end
203
- end
204
- end