Commit 82bfc966 by John Doe

remove missing files and folders on update

parent 3720f9af
...@@ -7,6 +7,12 @@ class UpdateFolder ...@@ -7,6 +7,12 @@ class UpdateFolder
def initialize(folder, entries) def initialize(folder, entries)
@folder = folder @folder = folder
@entries = entries @entries = entries
# initialiaze array of current entries, ids are removed
# as they are updated, so any id's left in this
# array are no longer present on the remote db
# and will be destroyed
@subfolder_ids = folder.subfolders.ids
@file_ids = folder.db_files.ids
super() super()
end end
...@@ -18,6 +24,20 @@ class UpdateFolder ...@@ -18,6 +24,20 @@ class UpdateFolder
info.slice(*DbFolder.defined_attributes)) info.slice(*DbFolder.defined_attributes))
# process the contents of the folder # process the contents of the folder
__parse_folder_entries(@folder, @entries) __parse_folder_entries(@folder, @entries)
# delete any files or folders still in the
# tracked ID arrays, they haven't been touched
# so they must have been removed from the remote
# db some other way (eg nilmtool)
unless @file_ids.empty?
@folder.db_files.destroy(*@file_ids)
add_warning('Removed files no longer in the remote database')
end
unless @subfolder_ids.empty?
@folder.subfolders.destroy(*@subfolder_ids)
add_warning('Removed folders no longer in the remote database')
end
# save the result # save the result
@folder.save! @folder.save!
self self
...@@ -103,14 +123,16 @@ class UpdateFolder ...@@ -103,14 +123,16 @@ class UpdateFolder
default_name) default_name)
base = __base_entry(entry_group) base = __base_entry(entry_group)
unless base # corrupt file, don't process unless base # corrupt file, don't process
@warnings << "#{entry_group.count} orphan decimations in #{folder.name}" add_warning("#{entry_group.count} orphan decimations in #{folder.name}")
return return
end end
# find or create the file # find or create the file
file = folder.db_files.find_by_path(base[:path]) file = folder.db_files.find_by_path(base[:path])
file ||= DbFile.new(db_folder: folder, file ||= DbFile.new(db_folder: folder,
path: base[:path], name: default_name) path: base[:path], name: default_name)
# remove the id (if present) to mark this file as updated
@file_ids -= [file.id]
# return the Updater, don't run it
UpdateFile.new(file, base, entry_group - [base]) UpdateFile.new(file, base, entry_group - [base])
end end
...@@ -131,6 +153,9 @@ class UpdateFolder ...@@ -131,6 +153,9 @@ class UpdateFolder
path = __build_path(entries) path = __build_path(entries)
folder = parent.subfolders.find_by_path(path) folder = parent.subfolders.find_by_path(path)
folder ||= DbFolder.new(parent: parent, path: path, name: default_name) folder ||= DbFolder.new(parent: parent, path: path, name: default_name)
# remove the id (if present) to mark this folder as updated
@subfolder_ids -= [folder.id]
# return the Updater, don't run it
UpdateFolder.new(folder, entries) UpdateFolder.new(folder, entries)
end end
......
...@@ -22,6 +22,8 @@ module ServiceStatus ...@@ -22,6 +22,8 @@ module ServiceStatus
end end
def add_error(message) def add_error(message)
# ignore duplicates
return if @errors.include?(message)
@errors << String(message) @errors << String(message)
end end
...@@ -30,6 +32,8 @@ module ServiceStatus ...@@ -30,6 +32,8 @@ module ServiceStatus
end end
def add_warning(message) def add_warning(message)
# ignore duplicates
return if @warnings.include?(message)
@warnings << String(message) @warnings << String(message)
end end
......
...@@ -25,12 +25,12 @@ simple_db = [ ...@@ -25,12 +25,12 @@ simple_db = [
describe 'UpdateDb' do describe 'UpdateDb' do
describe '*run*' do describe '*run*' do
def update_with_schema(schema) def update_with_schema(schema, db: nil)
# stub the database adapter # stub the database adapter
adapter = instance_double(DbAdapter) adapter = instance_double(DbAdapter)
allow(adapter).to receive(:schema).and_return(Array.new(schema)) allow(adapter).to receive(:schema).and_return(Array.new(schema))
# run the update # run the update
@db = Db.new @db = db || Db.new
@service = UpdateDb.new(db: @db) @service = UpdateDb.new(db: @db)
@service.run(db_adapter: adapter) @service.run(db_adapter: adapter)
@root = @db.root_folder @root = @db.root_folder
...@@ -129,8 +129,41 @@ describe 'UpdateDb' do ...@@ -129,8 +129,41 @@ describe 'UpdateDb' do
# updates to remote db # updates to remote db
describe 'given changes to remote db' do describe 'given changes to remote db' do
it 'removes missing files' it 'removes missing files' do
it 'removes missing folders' # create Db with a file 'temp'
update_with_schema([helper.entry('/folder1/temp'),
helper.entry('/folder1/info',
metadata: { name: 'f1' })
])
temp = DbFile.find_by_name('temp')
# the file 'temp' should be here
expect(temp).to be_present
# update Db without 'temp'
update_with_schema([helper.entry('/folder1/info',
metadata: { name: 'f1' })
], db: @db)
# it should be gone
expect(DbFile.find_by_name('temp')).to be nil
# ...and the service should have a warning
expect(@service.warnings?).to be true
end
it 'removes missing folders' do
# create Db with a folder 'temp'
update_with_schema([helper.entry('/folder1/stub'),
helper.entry('/folder1/temp/info',
metadata: { name: 'temp' })
])
temp = DbFolder.find_by_name('temp')
# the file 'temp' should be here
expect(temp).to be_present
# update Db without 'temp'
update_with_schema([helper.entry('/folder1/stub')],
db: @db)
# it should be gone
expect(DbFolder.find_by_name('temp')).to be nil
# ...and the service should have a warning
expect(@service.warnings?).to be true
end
it 'adds new files' it 'adds new files'
it 'adds new folders' it 'adds new folders'
end end
......
...@@ -26,6 +26,13 @@ describe 'ServiceStatus' do ...@@ -26,6 +26,13 @@ describe 'ServiceStatus' do
expect(x.warnings.length).to eq(1) expect(x.warnings.length).to eq(1)
end end
it 'ignores duplicate messages' do
x = ModuleTester.new
x.add_error('the same thing')
x.add_error('the same thing')
expect(x.errors.length).to eq(1)
end
it 'raises error if *run* is not implemented' do it 'raises error if *run* is not implemented' do
x = ModuleTester.new x = ModuleTester.new
expect { x.run }.to raise_error(RuntimeError) expect { x.run }.to raise_error(RuntimeError)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment