Explorar el Código

Merge pull request #5906 from nextcloud/backport/5890/stable-3.9

[stable-3.9] Create placeholder while dehydrating if needed
Matthieu Gallien hace 2 años
padre
commit
ecb5b5c054
Se han modificado 2 ficheros con 64 adiciones y 20 borrados
  1. 32 20
      src/libsync/vfs/cfapi/cfapiwrapper.cpp
  2. 32 0
      test/testsynccfapi.cpp

+ 32 - 20
src/libsync/vfs/cfapi/cfapiwrapper.cpp

@@ -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;

+ 32 - 0
test/testsynccfapi.cpp

@@ -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);