Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stable-3.9] Create placeholder while dehydrating if needed #5906

Merged
merged 1 commit into from
Jul 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
52 changes: 32 additions & 20 deletions src/libsync/vfs/cfapi/cfapiwrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -796,29 +796,41 @@ OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> OCC::CfApiWrapper::de
return {QString{"Could not update metadata due to invalid modification time for %1: %2"}.arg(path).arg(modtime)};
}

const auto info = findPlaceholderInfo(path);
if (!info) {
return { "Can't update non existing placeholder info" };
}

const auto fileIdentity = QString::fromUtf8(fileId).toStdWString();
const auto fileIdentitySize = (fileIdentity.length() + 1) * sizeof(wchar_t);

CF_FILE_RANGE dehydrationRange;
dehydrationRange.StartingOffset.QuadPart = 0;
dehydrationRange.Length.QuadPart = size;

const qint64 result = CfUpdatePlaceholder(handleForPath(path).get(), nullptr,
fileIdentity.data(), sizeToDWORD(fileIdentitySize),
&dehydrationRange,
1,
CF_UPDATE_FLAG_MARK_IN_SYNC | CF_UPDATE_FLAG_DEHYDRATE,
nullptr,
nullptr);

if (result != S_OK) {
qCWarning(lcCfApiWrapper) << "Couldn't update placeholder info for" << path << ":" << QString::fromWCharArray(_com_error(result).ErrorMessage());
return { "Couldn't update placeholder info" };
const auto info = findPlaceholderInfo(path);
if (info) {
CF_FILE_RANGE dehydrationRange;
dehydrationRange.StartingOffset.QuadPart = 0;
dehydrationRange.Length.QuadPart = size;

const qint64 result = CfUpdatePlaceholder(handleForPath(path).get(),
nullptr,
fileIdentity.data(),
sizeToDWORD(fileIdentitySize),
&dehydrationRange,
1,
CF_UPDATE_FLAG_MARK_IN_SYNC | CF_UPDATE_FLAG_DEHYDRATE,
nullptr,
nullptr);

if (result != S_OK) {
qCWarning(lcCfApiWrapper) << "Couldn't update placeholder info for" << path << ":" << QString::fromWCharArray(_com_error(result).ErrorMessage());
return {"Couldn't update placeholder info"};
}
} else {
const qint64 result = CfConvertToPlaceholder(handleForPath(path).get(),
fileIdentity.data(),
sizeToDWORD(fileIdentitySize),
CF_CONVERT_FLAG_MARK_IN_SYNC | CF_CONVERT_FLAG_DEHYDRATE,
nullptr,
nullptr);

if (result != S_OK) {
qCWarning(lcCfApiWrapper) << "Couldn't convert to placeholder" << path << ":" << QString::fromWCharArray(_com_error(result).ErrorMessage());
return {"Couldn't convert to placeholder"};
}
}

return OCC::Vfs::ConvertToPlaceholderResult::Ok;
Expand Down
32 changes: 32 additions & 0 deletions test/testsynccfapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,38 @@ private slots:
QTest::newRow("skip local discovery") << false;
}

void testReplaceOnlineOnlyFile()
{
FakeFolder fakeFolder{FileInfo{}};
auto vfs = setupVfs(fakeFolder);

// Create a new local (non-placeholder) file
fakeFolder.localModifier().insert("file");
QVERIFY(!vfs->pinState("file").isValid());

CopyFile(QString(fakeFolder.localPath() + "file").toStdWString().data(), QString(fakeFolder.localPath() + "file1").toStdWString().data(), false);

// Sync the files: files should be converted to placeholder files
QVERIFY(fakeFolder.syncOnce());
QVERIFY(vfs->pinState("file").isValid());

// Convert to Online Only
::setPinState(fakeFolder.localPath() + "file", PinState::OnlineOnly, cfapi::Recurse);

QVERIFY(fakeFolder.syncOnce());
QCOMPARE(*vfs->pinState("file"), PinState::OnlineOnly);
CFVERIFY_VIRTUAL(fakeFolder, "file");

// Replace the file
CopyFile(QString(fakeFolder.localPath() + "file1").toStdWString().data(), QString(fakeFolder.localPath() + "file").toStdWString().data(), false);

// Sync again: file should be correctly dehydrated again without error.
QVERIFY(fakeFolder.syncOnce());
QVERIFY(vfs->pinState("file").isValid());
QCOMPARE(*vfs->pinState("file"), PinState::OnlineOnly);
CFVERIFY_VIRTUAL(fakeFolder, "file");
}

void testVirtualFileLifecycle()
{
QFETCH(bool, doLocalDiscovery);
Expand Down