QString localDir;
+ //
+ // Build lookup tables for local, remote and db entries.
+ // For suffix-virtual files, the key will always be the base file name
+ // without the suffix.
+ //
std::set<QString> entriesNames; // sorted
QHash<QString, RemoteInfo> serverEntriesHash;
QHash<QString, LocalInfo> localEntriesHash;
QHash<QString, SyncJournalFileRecord> dbEntriesHash;
+
for (auto &e : _serverEntries) {
entriesNames.insert(e.name);
serverEntriesHash[e.name] = std::move(e);
}
_serverEntries.clear();
+
for (auto &e : _localEntries) {
// Remove the virtual file suffix
auto name = e.name;
if (e.name.endsWith(_discoveryData->_syncOptions._virtualFileSuffix)) {
e.isVirtualFile = true;
- name = e.name.left(e.name.size() - _discoveryData->_syncOptions._virtualFileSuffix.size());
+ name.chop(_discoveryData->_syncOptions._virtualFileSuffix.size());
if (localEntriesHash.contains(name))
continue; // If there is both a virtual file and a real file, we must keep the real file
}
}
_localEntries.clear();
-
// fetch all the name from the DB
auto pathU8 = _currentFolder._original.toUtf8();
// FIXME do that better (a query that do not get stuff recursively ?)
return;
}
-
+ //
+ // Iterate over entries and process them
+ //
for (const auto &f : entriesNames) {
auto localEntry = localEntriesHash.value(f);
auto serverEntry = serverEntriesHash.value(f);
SyncJournalFileRecord record = dbEntriesHash.value(f);
PathTuple path;
- if ((localEntry.isValid() && localEntry.isVirtualFile)) {
- Q_ASSERT(localEntry.name.endsWith(_discoveryData->_syncOptions._virtualFileSuffix));
- path = _currentFolder.addName(localEntry.name);
- path._server.chop(_discoveryData->_syncOptions._virtualFileSuffix.size());
- } else if (_queryLocal == ParentNotChanged && record.isValid() && record._type == ItemTypeVirtualFile) {
+ // If there's a local virtual file, the server path should not have the suffix
+ // but local/original/db should have it.
+ if ((localEntry.isValid() && localEntry.isVirtualFile)
+ || (_queryLocal == ParentNotChanged && record.isValid() && record._type == ItemTypeVirtualFile)) {
+ Q_ASSERT(!localEntry.isValid() || localEntry.name.endsWith(_discoveryData->_syncOptions._virtualFileSuffix));
QString name = f + _discoveryData->_syncOptions._virtualFileSuffix;
path = _currentFolder.addName(name);
path._server.chop(_discoveryData->_syncOptions._virtualFileSuffix.size());
item->_file = path._target;
item->_originalFile = path._original;
- if (_queryServer == NormalQuery && serverEntry.isValid()) {
+ if (serverEntry.isValid()) {
processFileAnalyzeRemoteInfo(item, path, localEntry, serverEntry, dbEntry);
return;
- } else if (_queryServer == ParentNotChanged && dbEntry._type == ItemTypeVirtualFileDownload) {
- // download virtual file
+ }
+
+ // Downloading a virtual file is like a server action and can happen even if
+ // server-side nothing has changed
+ if (_queryServer == ParentNotChanged && dbEntry._type == ItemTypeVirtualFileDownload) {
item->_direction = SyncFileItem::Down;
item->_instruction = CSYNC_INSTRUCTION_NEW;
Q_ASSERT(item->_file.endsWith(_discoveryData->_syncOptions._virtualFileSuffix));
return result;
}
};
- // Called once _serverEntries and _localEntries are filled
+
+ /** Iterate over entries inside the directory (non-recursively).
+ *
+ * Called once _serverEntries and _localEntries are filled
+ * Calls processFile() for each non-excluded one.
+ * Will start scheduling subdir jobs when done.
+ */
void process();
+
// return true if the file is excluded
bool handleExcluded(const QString &path, bool isDirectory, bool isHidden, bool isSymlink);
+
+ /** Reconcile local/remote/db information for a single item.
+ *
+ * Can be a file or a directory.
+ * Usually ends up emitting itemDiscovered() or creating a subdirectory job.
+ *
+ * This main function delegates some work to the processFile* functions.
+ */
void processFile(PathTuple, const LocalInfo &, const RemoteInfo &, const SyncJournalFileRecord &);
+
+ /// processFile helper for when remote information is available, typically flows into AnalyzeLocalInfo when done
void processFileAnalyzeRemoteInfo(const SyncFileItemPtr &item, PathTuple, const LocalInfo &, const RemoteInfo &, const SyncJournalFileRecord &);
+
+ /// processFile helper for reconciling local changes
void processFileAnalyzeLocalInfo(const SyncFileItemPtr &item, PathTuple, const LocalInfo &, const RemoteInfo &, const SyncJournalFileRecord &, QueryMode recurseQueryServer);
+
+ /// processFile helper for common final processing
void processFileFinalize(const SyncFileItemPtr &item, PathTuple, bool recurse, QueryMode recurseQueryLocal, QueryMode recurseQueryServer);