Deletion detection
diff --git a/src/dispatcher.cc b/src/dispatcher.cc
index 03de6a9..cc677b6 100644
--- a/src/dispatcher.cc
+++ b/src/dispatcher.cc
@@ -118,6 +118,12 @@
   m_server->deregisterPrefix(oldLocalPrefix);
 }
 
+void
+Dispatcher::Restore_LocalFile (FileItemPtr file)
+{
+  m_executor.execute (bind (&Dispatcher::Restore_LocalFile_Execute, this, file));
+}
+
 /////////////////////////////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -387,3 +393,29 @@
       permissions (filePath, static_cast<filesystem::perms> (file->mode ()));
     }
 }
+
+void
+Dispatcher::Restore_LocalFile_Execute (FileItemPtr file)
+{
+  _LOG_DEBUG ("Got request to restore local file [" << file->filename () << "]");
+  // the rest will gracefully fail if object-db is missing or incomplete
+
+  boost::filesystem::path filePath = m_rootDir / file->filename ();
+  Name deviceName (file->device_name ().c_str (), file->device_name ().size ());
+  Hash hash (file->file_hash ().c_str (), file->file_hash ().size ());
+
+  if (filesystem::exists (filePath) &&
+      filesystem::last_write_time (filePath) == file->mtime () &&
+      filesystem::status (filePath).permissions () == static_cast<filesystem::perms> (file->mode ()) &&
+      *Hash::FromFileContent (filePath) == hash)
+    {
+      _LOG_DEBUG ("Asking to assemble a file, but file already exists on a filesystem");
+      return;
+    }
+
+  m_objectManager.objectsToLocalFile (deviceName, hash, filePath);
+
+  last_write_time (filePath, file->mtime ());
+  permissions (filePath, static_cast<filesystem::perms> (file->mode ()));
+
+}