Skip to content

Commit

Permalink
Normalize file names before using them as keys
Browse files Browse the repository at this point in the history
On macOS the filenames on disk are stored in NFD form. When the original
filename on the server was in NFC form, the filenames wouldn't match,
and a MOVE or DELETE+PUT would be triggered.

This changes converts all filenames to NFC form during local discovery.
  • Loading branch information
erikjv committed Dec 5, 2024
1 parent 19751ff commit 039c965
Showing 1 changed file with 17 additions and 4 deletions.
21 changes: 17 additions & 4 deletions src/libsync/discovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,13 @@ void ProcessDirectoryJob::process()
RemoteInfo serverEntry;
LocalInfo localEntry;
};

// The key for the `entries` mapping is the NFC form of the filename. This is done to prevent
// NFC->NFD or NFD->NFC conversions done by `QFile` and/or the underlying local filesystem.
std::map<QString, Entries> entries;
for (auto &e : _serverNormalQueryEntries) {
entries[e.name].serverEntry = std::move(e);
// Keep the name on the server as-is, but use the NFC form as the key
entries[e.name.normalized(QString::NormalizationForm_C)].serverEntry = std::move(e);
}
_serverNormalQueryEntries.clear();

Expand All @@ -93,7 +97,7 @@ void ProcessDirectoryJob::process()
if (rec.isVirtualFile() && isVfsWithSuffix()) {
name = chopVirtualFileSuffix(name);
}
auto &dbEntry = entries[name].dbEntry;
auto &dbEntry = entries[name.normalized(QString::NormalizationForm_C)].dbEntry;
dbEntry = rec;
setupDbPinStateActions(dbEntry);
})) {
Expand All @@ -102,6 +106,7 @@ void ProcessDirectoryJob::process()
}

for (auto &e : _localNormalQueryEntries) {
e.name = e.name.normalized(QString::NormalizationForm_C);
entries[e.name].localEntry = e;
}
if (isVfsWithSuffix()) {
Expand Down Expand Up @@ -140,8 +145,16 @@ void ProcessDirectoryJob::process()
for (const auto &f : entries) {
const auto &e = f.second;

PathTuple path;
path = _currentFolder.addName(e.nameOverride.isEmpty() ? f.first : e.nameOverride);
QString name;
if (!e.nameOverride.isEmpty()) {
name = e.nameOverride;
} else if (!e.serverEntry.name.isEmpty()) {
// IF there is a name on the server, take that, as it hasn't been normalized.
name = e.serverEntry.name;
} else {
name = f.first;
}
PathTuple path = _currentFolder.addName(name);

if (isVfsWithSuffix()) {
// Without suffix vfs the paths would be good. But since the dbEntry and localEntry
Expand Down

0 comments on commit 039c965

Please sign in to comment.