Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/owncloud/client.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/troubleshooting.rst2
-rw-r--r--mirall.desktop.in3
-rw-r--r--src/gui/folderman.cpp3
-rw-r--r--src/gui/lockwatcher.cpp10
-rw-r--r--src/gui/lockwatcher.h6
-rw-r--r--src/gui/settingsdialog.cpp5
-rw-r--r--src/libsync/propagatedownload.cpp4
-rw-r--r--src/libsync/propagateuploadng.cpp5
-rw-r--r--src/libsync/propagateuploadv1.cpp3
-rw-r--r--test/CMakeLists.txt2
-rw-r--r--test/testlockedfiles.cpp163
-rw-r--r--translations/client_es.ts4
12 files changed, 202 insertions, 8 deletions
diff --git a/doc/troubleshooting.rst b/doc/troubleshooting.rst
index 1dc7b77ca..6ba165705 100644
--- a/doc/troubleshooting.rst
+++ b/doc/troubleshooting.rst
@@ -129,7 +129,7 @@ Logging to a Temporary Directory
1. Open the ownCloud Desktop Client.
-2. Press F12 on your keyboard.
+2. Press F12 or Ctrl-L on your keyboard.
The Log Output window opens.
diff --git a/mirall.desktop.in b/mirall.desktop.in
index 4b3a30b51..d7d0cb456 100644
--- a/mirall.desktop.in
+++ b/mirall.desktop.in
@@ -95,6 +95,9 @@ MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
# Translations
+
+
+# Translations
Comment[oc]=@APPLICATION_NAME@ sincronizacion del client
Icon[oc]=@APPLICATION_EXECUTABLE@
Name[oc]=@APPLICATION_NAME@ sincronizacion del client
diff --git a/src/gui/folderman.cpp b/src/gui/folderman.cpp
index a006a277a..753d83156 100644
--- a/src/gui/folderman.cpp
+++ b/src/gui/folderman.cpp
@@ -852,7 +852,8 @@ void FolderMan::slotServerVersionChanged(Account *account)
void FolderMan::slotWatchedFileUnlocked(const QString &path)
{
if (Folder *f = folderForPath(path)) {
- f->scheduleThisFolderSoon();
+ // Treat this equivalently to the file being reported by the file watcher
+ f->slotWatchedPathChanged(path);
}
}
diff --git a/src/gui/lockwatcher.cpp b/src/gui/lockwatcher.cpp
index cf76c097b..8e26cf2ce 100644
--- a/src/gui/lockwatcher.cpp
+++ b/src/gui/lockwatcher.cpp
@@ -38,6 +38,16 @@ void LockWatcher::addFile(const QString &path)
_watchedPaths.insert(path);
}
+void LockWatcher::setCheckInterval(std::chrono::milliseconds interval)
+{
+ _timer.start(interval.count());
+}
+
+bool LockWatcher::contains(const QString &path)
+{
+ return _watchedPaths.contains(path);
+}
+
void LockWatcher::checkFiles()
{
QSet<QString> unlocked;
diff --git a/src/gui/lockwatcher.h b/src/gui/lockwatcher.h
index ba2d8f8a7..ae8f2cd01 100644
--- a/src/gui/lockwatcher.h
+++ b/src/gui/lockwatcher.h
@@ -51,6 +51,12 @@ public:
*/
void addFile(const QString &path);
+ /** Adjusts the default interval for checking whether the lock is still present */
+ void setCheckInterval(std::chrono::milliseconds interval);
+
+ /** Whether the path is being watched for lock-changes */
+ bool contains(const QString &path);
+
signals:
/** Emitted when one of the watched files is no longer
* being locked. */
diff --git a/src/gui/settingsdialog.cpp b/src/gui/settingsdialog.cpp
index e1c36efd3..df30ba0d5 100644
--- a/src/gui/settingsdialog.cpp
+++ b/src/gui/settingsdialog.cpp
@@ -135,6 +135,11 @@ SettingsDialog::SettingsDialog(ownCloudGui *gui, QWidget *parent)
connect(showLogWindow, &QAction::triggered, gui, &ownCloudGui::slotToggleLogBrowser);
addAction(showLogWindow);
+ QAction *showLogWindow2 = new QAction(this);
+ showLogWindow2->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L));
+ connect(showLogWindow2, &QAction::triggered, gui, &ownCloudGui::slotToggleLogBrowser);
+ addAction(showLogWindow2);
+
customizeStyle();
cfg.restoreGeometry(this);
diff --git a/src/libsync/propagatedownload.cpp b/src/libsync/propagatedownload.cpp
index 34f23ee13..d02a56628 100644
--- a/src/libsync/propagatedownload.cpp
+++ b/src/libsync/propagatedownload.cpp
@@ -850,7 +850,9 @@ namespace { // Anonymous namespace for the recall feature
static void preserveGroupOwnership(const QString &fileName, const QFileInfo &fi)
{
#ifdef Q_OS_UNIX
- chown(fileName.toLocal8Bit().constData(), -1, fi.groupId());
+ if (chown(fileName.toLocal8Bit().constData(), -1, fi.groupId()) != 0) {
+ qCWarning(lcPropagateDownload) << "Unable to chown" << fileName << "to previous group owner" << strerror(errno);
+ }
#else
Q_UNUSED(fileName);
Q_UNUSED(fi);
diff --git a/src/libsync/propagateuploadng.cpp b/src/libsync/propagateuploadng.cpp
index 85bdc0ae5..e141bcc86 100644
--- a/src/libsync/propagateuploadng.cpp
+++ b/src/libsync/propagateuploadng.cpp
@@ -37,6 +37,7 @@ extern "C" {
#include <cmath>
#include <cstring>
+#include <memory>
namespace OCC {
@@ -541,7 +542,7 @@ void PropagateUploadFileNG::startNextChunk()
_currentChunkOffset = _rangesToUpload.first().start;
_currentChunkSize = qMin(propagator()->_chunkSize, _rangesToUpload.first().size);
- auto device = std::make_unique<UploadDevice>(&propagator()->_bandwidthManager);
+ auto device = std::unique_ptr<UploadDevice>(new UploadDevice(&propagator()->_bandwidthManager));
const QString fileName = propagator()->getFilePath(_item->_file);
if (!device->prepareAndOpen(fileName, _currentChunkOffset, _currentChunkSize)) {
@@ -582,7 +583,7 @@ void PropagateUploadFileNG::slotZsyncGenerationFinished(const QString &generated
<< "Finished generation of:" << generatedFileName
<< "size:" << FileSystem::getSize(generatedFileName);
- auto device = std::make_unique<UploadDevice>(&propagator()->_bandwidthManager);
+ auto device = std::unique_ptr<UploadDevice>(new UploadDevice(&propagator()->_bandwidthManager));
if (!device->prepareAndOpen(generatedFileName, 0, FileSystem::getSize(generatedFileName))) {
qCWarning(lcPropagateUpload) << "Could not prepare generated file: " << generatedFileName << device->errorString();
diff --git a/src/libsync/propagateuploadv1.cpp b/src/libsync/propagateuploadv1.cpp
index 68aab4172..c24e7b648 100644
--- a/src/libsync/propagateuploadv1.cpp
+++ b/src/libsync/propagateuploadv1.cpp
@@ -32,6 +32,7 @@
#include <QDir>
#include <cmath>
#include <cstring>
+#include <memory>
namespace OCC {
@@ -90,7 +91,7 @@ void PropagateUploadFileV1::startNextChunk()
QString path = _item->_file;
- auto device = std::make_unique<UploadDevice>(&propagator()->_bandwidthManager);
+ auto device = std::unique_ptr<UploadDevice>(new UploadDevice(&propagator()->_bandwidthManager));
qint64 chunkStart = 0;
qint64 currentChunkSize = fileSize;
bool isFinalChunk = false;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 1f078a665..1a26ace2e 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -56,6 +56,8 @@ owncloud_add_test(LocalDiscovery "syncenginetestutils.h")
owncloud_add_test(RemoteDiscovery "syncenginetestutils.h")
owncloud_add_test(Permissions "syncenginetestutils.h")
owncloud_add_test(SelectiveSync "syncenginetestutils.h")
+owncloud_add_test(LockedFiles "syncenginetestutils.h;../src/gui/lockwatcher.cpp")
+
owncloud_add_test(FolderWatcher "${FolderWatcher_SRC}")
if( UNIX AND NOT APPLE )
diff --git a/test/testlockedfiles.cpp b/test/testlockedfiles.cpp
new file mode 100644
index 000000000..df1e8f8d0
--- /dev/null
+++ b/test/testlockedfiles.cpp
@@ -0,0 +1,163 @@
+/*
+ * This software is in the public domain, furnished "as is", without technical
+ * support, and with no warranty, express or implied, as to its usefulness for
+ * any purpose.
+ *
+ */
+
+#include <QtTest>
+#include "syncenginetestutils.h"
+#include "lockwatcher.h"
+#include <syncengine.h>
+#include <localdiscoverytracker.h>
+
+using namespace OCC;
+
+#ifdef Q_OS_WIN
+// pass combination of FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_DELETE
+HANDLE makeHandle(const QString &file, int shareMode)
+{
+ const wchar_t *wuri = reinterpret_cast<const wchar_t *>(file.utf16());
+ auto handle = CreateFileW(
+ wuri,
+ GENERIC_READ | GENERIC_WRITE,
+ shareMode,
+ NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (handle == INVALID_HANDLE_VALUE) {
+ qWarning() << GetLastError();
+ }
+ return handle;
+}
+#endif
+
+class TestLockedFiles : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testBasicLockFileWatcher()
+ {
+ int count = 0;
+ QString file;
+
+ LockWatcher watcher;
+ watcher.setCheckInterval(std::chrono::milliseconds(50));
+ connect(&watcher, &LockWatcher::fileUnlocked, &watcher, [&](const QString &f) { ++count; file = f; });
+
+ QString tmpFile;
+ {
+ QTemporaryFile tmp;
+ tmp.setAutoRemove(false);
+ tmp.open();
+ tmpFile = tmp.fileName();
+ }
+ QVERIFY(QFile::exists(tmpFile));
+
+ QVERIFY(!FileSystem::isFileLocked(tmpFile));
+ watcher.addFile(tmpFile);
+ QVERIFY(watcher.contains(tmpFile));
+
+ QEventLoop loop;
+ QTimer::singleShot(120, &loop, [&] { loop.exit(); });
+ loop.exec();
+
+ QCOMPARE(count, 1);
+ QCOMPARE(file, tmpFile);
+ QVERIFY(!watcher.contains(tmpFile));
+
+#ifdef Q_OS_WIN
+ auto h = makeHandle(tmpFile, 0);
+ QVERIFY(FileSystem::isFileLocked(tmpFile));
+ watcher.addFile(tmpFile);
+
+ count = 0;
+ file.clear();
+ QThread::msleep(120);
+ qApp->processEvents();
+
+ QCOMPARE(count, 0);
+ QVERIFY(file.isEmpty());
+ QVERIFY(watcher.contains(tmpFile));
+
+ CloseHandle(h);
+ QVERIFY(!FileSystem::isFileLocked(tmpFile));
+
+ QThread::msleep(120);
+ qApp->processEvents();
+
+ QCOMPARE(count, 1);
+ QCOMPARE(file, tmpFile);
+ QVERIFY(!watcher.contains(tmpFile));
+#endif
+ QFile::remove(tmpFile);
+ }
+
+#ifdef Q_OS_WIN
+ void testLockedFilePropagation()
+ {
+ FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
+
+ QStringList seenLockedFiles;
+ connect(&fakeFolder.syncEngine(), &SyncEngine::seenLockedFile, &fakeFolder.syncEngine(),
+ [&](const QString &file) { seenLockedFiles.append(file); });
+
+ LocalDiscoveryTracker tracker;
+ connect(&fakeFolder.syncEngine(), &SyncEngine::itemCompleted, &tracker, &LocalDiscoveryTracker::slotItemCompleted);
+ connect(&fakeFolder.syncEngine(), &SyncEngine::finished, &tracker, &LocalDiscoveryTracker::slotSyncFinished);
+ auto hasLocalDiscoveryPath = [&](const QString &path) {
+ auto &paths = tracker.localDiscoveryPaths();
+ return paths.find(path.toUtf8()) != paths.end();
+ };
+
+ //
+ // Local change, attempted upload, but file is locked!
+ //
+ fakeFolder.localModifier().appendByte("A/a1");
+ tracker.addTouchedPath("A/a1");
+ auto h1 = makeHandle(fakeFolder.localPath() + "A/a1", 0);
+
+ fakeFolder.syncEngine().setLocalDiscoveryOptions(LocalDiscoveryStyle::DatabaseAndFilesystem, tracker.localDiscoveryPaths());
+ tracker.startSyncPartialDiscovery();
+ QVERIFY(!fakeFolder.syncOnce());
+
+ QVERIFY(seenLockedFiles.contains(fakeFolder.localPath() + "A/a1"));
+ QVERIFY(seenLockedFiles.size() == 1);
+ QVERIFY(hasLocalDiscoveryPath("A/a1"));
+
+ CloseHandle(h1);
+
+ fakeFolder.syncEngine().setLocalDiscoveryOptions(LocalDiscoveryStyle::DatabaseAndFilesystem, tracker.localDiscoveryPaths());
+ tracker.startSyncPartialDiscovery();
+ QVERIFY(fakeFolder.syncOnce());
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+
+ seenLockedFiles.clear();
+ QVERIFY(tracker.localDiscoveryPaths().empty());
+
+ //
+ // Remote change, attempted download, but file is locked!
+ //
+ fakeFolder.remoteModifier().appendByte("A/a1");
+ auto h2 = makeHandle(fakeFolder.localPath() + "A/a1", 0);
+
+ fakeFolder.syncEngine().setLocalDiscoveryOptions(LocalDiscoveryStyle::DatabaseAndFilesystem, tracker.localDiscoveryPaths());
+ tracker.startSyncPartialDiscovery();
+ QVERIFY(!fakeFolder.syncOnce());
+
+ QVERIFY(seenLockedFiles.contains(fakeFolder.localPath() + "A/a1"));
+ QVERIFY(seenLockedFiles.size() == 1);
+
+ CloseHandle(h2);
+
+ fakeFolder.syncEngine().setLocalDiscoveryOptions(LocalDiscoveryStyle::DatabaseAndFilesystem, tracker.localDiscoveryPaths());
+ tracker.startSyncPartialDiscovery();
+ QVERIFY(fakeFolder.syncOnce());
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+ }
+#endif
+};
+
+QTEST_GUILESS_MAIN(TestLockedFiles)
+#include "testlockedfiles.moc"
diff --git a/translations/client_es.ts b/translations/client_es.ts
index 65677ea08..79ab99fb3 100644
--- a/translations/client_es.ts
+++ b/translations/client_es.ts
@@ -1375,12 +1375,12 @@ Si continua con la sincronización todos los archivos serán remplazados por su
<message>
<location filename="../src/gui/generalsettings.ui" line="80"/>
<source>&amp;Update Channel</source>
- <translation type="unfinished"/>
+ <translation>&amp;Actualizar canal</translation>
</message>
<message>
<location filename="../src/gui/generalsettings.ui" line="186"/>
<source>•</source>
- <translation type="unfinished"/>
+ <translation>•</translation>
</message>
<message>
<location filename="../src/gui/generalsettings.ui" line="236"/>