|
|
@@ -175,7 +175,8 @@ bool PropagateItemJob::checkForProblemsWithShared(int httpStatusCode, const QStr
|
|
|
if( httpStatusCode == 403 && _propagator->isInSharedDirectory(_item->_file )) {
|
|
|
if( !_item->_isDirectory ) {
|
|
|
SyncFileItemPtr downloadItem(new SyncFileItem(*_item));
|
|
|
- if (downloadItem->_instruction == CSYNC_INSTRUCTION_NEW) {
|
|
|
+ if (downloadItem->_instruction == CSYNC_INSTRUCTION_NEW
|
|
|
+ || downloadItem->_instruction == CSYNC_INSTRUCTION_TYPE_CHANGE) {
|
|
|
// don't try to recover pushing new files
|
|
|
return false;
|
|
|
} else if (downloadItem->_instruction == CSYNC_INSTRUCTION_SYNC) {
|
|
|
@@ -234,32 +235,39 @@ void PropagateItemJob::slotRestoreJobCompleted(const SyncFileItem& item )
|
|
|
// ================================================================================
|
|
|
|
|
|
PropagateItemJob* OwncloudPropagator::createJob(const SyncFileItemPtr &item) {
|
|
|
+ bool deleteExisting = item->_instruction == CSYNC_INSTRUCTION_TYPE_CHANGE;
|
|
|
switch(item->_instruction) {
|
|
|
case CSYNC_INSTRUCTION_REMOVE:
|
|
|
if (item->_direction == SyncFileItem::Down) return new PropagateLocalRemove(this, item);
|
|
|
else return new PropagateRemoteDelete(this, item);
|
|
|
case CSYNC_INSTRUCTION_NEW:
|
|
|
+ case CSYNC_INSTRUCTION_TYPE_CHANGE:
|
|
|
if (item->_isDirectory) {
|
|
|
- if (item->_direction == SyncFileItem::Down) return new PropagateLocalMkdir(this, item);
|
|
|
- else return new PropagateRemoteMkdir(this, item);
|
|
|
+ if (item->_direction == SyncFileItem::Down) {
|
|
|
+ auto job = new PropagateLocalMkdir(this, item);
|
|
|
+ job->setDeleteExistingFile(deleteExisting);
|
|
|
+ return job;
|
|
|
+ } else {
|
|
|
+ auto job = new PropagateRemoteMkdir(this, item);
|
|
|
+ job->setDeleteExisting(deleteExisting);
|
|
|
+ return job;
|
|
|
+ }
|
|
|
} //fall through
|
|
|
case CSYNC_INSTRUCTION_SYNC:
|
|
|
case CSYNC_INSTRUCTION_CONFLICT:
|
|
|
if (item->_isDirectory) {
|
|
|
- // Did a file turn into a directory?
|
|
|
- if (QFileInfo(getFilePath(item->_file)).isFile()) {
|
|
|
- auto job = new PropagateLocalMkdir(this, item);
|
|
|
- job->setDeleteExistingFile(true);
|
|
|
- return job;
|
|
|
- }
|
|
|
// Should we set the mtime?
|
|
|
return 0;
|
|
|
}
|
|
|
{
|
|
|
if (item->_direction != SyncFileItem::Up) {
|
|
|
- return new PropagateDownloadFileQNAM(this, item);
|
|
|
+ auto job = new PropagateDownloadFileQNAM(this, item);
|
|
|
+ job->setDeleteExistingFolder(deleteExisting);
|
|
|
+ return job;
|
|
|
} else {
|
|
|
- return new PropagateUploadFileQNAM(this, item);
|
|
|
+ auto job = new PropagateUploadFileQNAM(this, item);
|
|
|
+ job->setDeleteExisting(deleteExisting);
|
|
|
+ return job;
|
|
|
}
|
|
|
}
|
|
|
case CSYNC_INSTRUCTION_RENAME:
|
|
|
@@ -320,7 +328,9 @@ void OwncloudPropagator::start(const SyncFileItemVector& items)
|
|
|
delDirJob->increaseAffectedCount();
|
|
|
}
|
|
|
continue;
|
|
|
- } else if (item->_instruction == CSYNC_INSTRUCTION_NEW && item->_isDirectory) {
|
|
|
+ } else if (item->_isDirectory
|
|
|
+ && (item->_instruction == CSYNC_INSTRUCTION_NEW
|
|
|
+ || item->_instruction == CSYNC_INSTRUCTION_TYPE_CHANGE)) {
|
|
|
// create a new directory within a deleted directory? That can happen if the directory
|
|
|
// etag was not fetched properly on the previous sync because the sync was aborted
|
|
|
// while uploading this directory (which is now removed). We can ignore it.
|
|
|
@@ -345,6 +355,22 @@ void OwncloudPropagator::start(const SyncFileItemVector& items)
|
|
|
if (item->_isDirectory) {
|
|
|
PropagateDirectory *dir = new PropagateDirectory(this, item);
|
|
|
dir->_firstJob.reset(createJob(item));
|
|
|
+
|
|
|
+ if (item->_instruction == CSYNC_INSTRUCTION_TYPE_CHANGE
|
|
|
+ && item->_direction == SyncFileItem::Up) {
|
|
|
+ // Skip all potential uploads to the new folder.
|
|
|
+ // Processing them now leads to problems with permissions:
|
|
|
+ // checkForPermissions() has already run and used the permissions
|
|
|
+ // of the file we're about to delete to decide whether uploading
|
|
|
+ // to the new dir is ok...
|
|
|
+ foreach(const SyncFileItemPtr &item2, items) {
|
|
|
+ if (item2->destination().startsWith(item->destination() + "/")) {
|
|
|
+ item2->_instruction = CSYNC_INSTRUCTION_NONE;
|
|
|
+ _anotherSyncNeeded = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if (item->_instruction == CSYNC_INSTRUCTION_REMOVE) {
|
|
|
// We do the removal of directories at the end, because there might be moves from
|
|
|
// these directories that will happen later.
|
|
|
@@ -364,23 +390,10 @@ void OwncloudPropagator::start(const SyncFileItemVector& items)
|
|
|
}
|
|
|
directories.push(qMakePair(item->destination() + "/" , dir));
|
|
|
} else if (PropagateItemJob* current = createJob(item)) {
|
|
|
- // If the target of a job is currently a directory, we need to remove it!
|
|
|
- // This can happen when what used to be a directory changed to a file on the
|
|
|
- // server an a PropagateLocalRename or PropageDownload job wants to run.
|
|
|
- if (item->_direction == SyncFileItem::Down
|
|
|
- && QFileInfo(getFilePath(item->_file)).isDir()) {
|
|
|
- // The DirectoryConflict job *must* run before the file propagation job
|
|
|
- // and we also need to make sure other jobs that deal with the files
|
|
|
- // in the directory (like removes or moves, in particular of other
|
|
|
- // directories!) run first.
|
|
|
- // Making it a directory job ensures that moves run first and that the
|
|
|
- // (potential) directory rename happens before the file propagation.
|
|
|
- // Prepending all jobs to directoriesToRemove ensures that removals of
|
|
|
- // subdirectories happen before the directory is renamed.
|
|
|
- PropagateDirectory *dir = new PropagateDirectory(this, item);
|
|
|
- dir->_firstJob.reset(new PropagateLocalDirectoryConflict(this, item));
|
|
|
- dir->append(current);
|
|
|
- directoriesToRemove.prepend(dir);
|
|
|
+ if (item->_instruction == CSYNC_INSTRUCTION_TYPE_CHANGE) {
|
|
|
+ // will delete directories, so defer execution
|
|
|
+ directoriesToRemove.prepend(current);
|
|
|
+ removedDirectory = item->_file + "/";
|
|
|
} else {
|
|
|
directories.top().second->append(current);
|
|
|
}
|