Skip to content

Commit

Permalink
Optimise recording deps on new items
Browse files Browse the repository at this point in the history
  • Loading branch information
denisdefreyne committed Dec 21, 2016
1 parent ea7e4bb commit 6443eaa
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 26 deletions.
24 changes: 13 additions & 11 deletions lib/nanoc/base/repos/dependency_store.rb
Expand Up @@ -11,7 +11,8 @@ def initialize(objects, env_name: nil)
super(Nanoc::Int::Store.tmp_path_for(env_name: env_name, store_name: 'dependencies'), 4)

@objects = objects
@graph = Nanoc::Int::DirectedGraph.new([nil] + @objects)
@new_objects = []
@graph = Nanoc::Int::DirectedGraph.new([nil] + @objects)
end

contract C::Or[Nanoc::Int::Item, Nanoc::Int::ItemRep, Nanoc::Int::Layout] => C::ArrayOf[Nanoc::Int::Dependency]
Expand Down Expand Up @@ -50,7 +51,11 @@ def dependencies_causing_outdatedness_of(object)
# predecessors of
# the given object
def objects_causing_outdatedness_of(object)
@graph.direct_predecessors_of(object)
if @new_objects.any?
[@new_objects.first]
else
@graph.direct_predecessors_of(object)
end
end

# Returns the direct inverse dependencies for the given object.
Expand All @@ -67,7 +72,11 @@ def objects_causing_outdatedness_of(object)
# @return [Array<Nanoc::Int::Item, Nanoc::Int::Layout>] The direct successors of
# the given object
def objects_outdated_due_to(object)
@graph.direct_successors_of(object).compact
if @new_objects.include?(object)
@objects
else
@graph.direct_successors_of(object).compact
end
end

contract C::Maybe[C::Or[Nanoc::Int::Item, Nanoc::Int::Layout]], C::Maybe[C::Or[Nanoc::Int::Item, Nanoc::Int::Layout]], C::KeywordArgs[raw_content: C::Optional[C::Bool], attributes: C::Optional[C::Bool], compiled_content: C::Optional[C::Bool], path: C::Optional[C::Bool]] => C::Any
Expand Down Expand Up @@ -141,14 +150,7 @@ def data=(new_data)
end

# Record dependency from all items on new items
new_objects = (@objects - previous_objects)
new_props = { raw_content: true, attributes: true, compiled_content: true, path: true }
new_objects.each do |new_obj|
@objects.each do |obj|
next unless obj.is_a?(Nanoc::Int::Item)
@graph.add_edge(new_obj, obj, props: new_props)
end
end
@new_objects = @objects - previous_objects
end
end
end
80 changes: 65 additions & 15 deletions spec/nanoc/base/repos/dependency_store_spec.rb
Expand Up @@ -121,30 +121,80 @@
store.record_dependency(obj_a, obj_b, attributes: true)

store.store
store.objects = objects_after
store.load
end

it 'has the right dependencies for item A' do
deps = store.dependencies_causing_outdatedness_of(obj_a)
expect(deps.size).to eql(1)
context 'no new objects' do
let(:objects_after) { objects }

expect(deps[0].from).to eql(obj_b)
expect(deps[0].to).to eql(obj_a)
it 'has the right dependencies for item A' do
deps = store.dependencies_causing_outdatedness_of(obj_a)
expect(deps.size).to eql(1)

expect(deps[0].from).to eql(obj_b)
expect(deps[0].to).to eql(obj_a)

expect(deps[0].props.raw_content?).to eq(false)
expect(deps[0].props.attributes?).to eq(true)
expect(deps[0].props.compiled_content?).to eq(true)
expect(deps[0].props.path?).to eq(false)
end

expect(deps[0].props.raw_content?).to eq(false)
expect(deps[0].props.attributes?).to eq(true)
expect(deps[0].props.compiled_content?).to eq(true)
expect(deps[0].props.path?).to eq(false)
it 'has the right dependencies for item B' do
deps = store.dependencies_causing_outdatedness_of(obj_b)
expect(deps).to be_empty
end

it 'has the right dependencies for item C' do
deps = store.dependencies_causing_outdatedness_of(obj_c)
expect(deps).to be_empty
end
end

it 'has the right dependencies for item B' do
deps = store.dependencies_causing_outdatedness_of(obj_b)
expect(deps).to be_empty
context 'one new object' do
let(:objects_after) do
[obj_a, obj_b, obj_c, obj_d]
end

let(:obj_d) { Nanoc::Int::Item.new('d', {}, '/d.md') }

it 'marks existing items as outdated' do
expect(store.objects_causing_outdatedness_of(obj_a)).to eq([obj_d])
expect(store.objects_causing_outdatedness_of(obj_b)).to eq([obj_d])
expect(store.objects_causing_outdatedness_of(obj_c)).to eq([obj_d])
end

it 'has the right target dependencies' do
expect(store.objects_outdated_due_to(obj_a)).to be_empty
expect(store.objects_outdated_due_to(obj_b)).to eq([obj_a])
expect(store.objects_outdated_due_to(obj_c)).to be_empty
expect(store.objects_outdated_due_to(obj_d)).to eq(objects_after)
end
end

it 'has the right dependencies for item C' do
deps = store.dependencies_causing_outdatedness_of(obj_c)
expect(deps).to be_empty
context 'two new objects' do
let(:objects_after) do
[obj_a, obj_b, obj_c, obj_d, obj_e]
end

let(:obj_d) { Nanoc::Int::Item.new('d', {}, '/d.md') }
let(:obj_e) { Nanoc::Int::Item.new('e', {}, '/e.md') }

it 'marks existing items as outdated' do
# Only one of obj D or E needed!
expect(store.objects_causing_outdatedness_of(obj_a)).to eq([obj_d]).or eq([obj_e])
expect(store.objects_causing_outdatedness_of(obj_b)).to eq([obj_d]).or eq([obj_e])
expect(store.objects_causing_outdatedness_of(obj_c)).to eq([obj_d]).or eq([obj_e])
end

it 'has the right target dependencies' do
expect(store.objects_outdated_due_to(obj_a)).to be_empty
expect(store.objects_outdated_due_to(obj_b)).to eq([obj_a])
expect(store.objects_outdated_due_to(obj_c)).to be_empty
expect(store.objects_outdated_due_to(obj_d)).to eq(objects_after)
expect(store.objects_outdated_due_to(obj_e)).to eq(objects_after)
end
end
end
end

0 comments on commit 6443eaa

Please sign in to comment.