diff --git a/app/src/main/java/com/nextcloud/client/database/dao/FileSystemDao.kt b/app/src/main/java/com/nextcloud/client/database/dao/FileSystemDao.kt index 3dc90d77b318..91a03044afde 100644 --- a/app/src/main/java/com/nextcloud/client/database/dao/FileSystemDao.kt +++ b/app/src/main/java/com/nextcloud/client/database/dao/FileSystemDao.kt @@ -19,6 +19,15 @@ interface FileSystemDao { @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertOrReplace(filesystemEntity: FilesystemEntity) + @Query( + """ + DELETE FROM ${ProviderMeta.ProviderTableMeta.FILESYSTEM_TABLE_NAME} + WHERE ${ProviderMeta.ProviderTableMeta.FILESYSTEM_FILE_LOCAL_PATH} = :localPath + AND ${ProviderMeta.ProviderTableMeta._ID} = :id + """ + ) + suspend fun deleteByLocalPathAndId(localPath: String, id: Int) + @Query( """ SELECT * diff --git a/app/src/main/java/com/nextcloud/client/jobs/autoUpload/AutoUploadWorker.kt b/app/src/main/java/com/nextcloud/client/jobs/autoUpload/AutoUploadWorker.kt index e1fc93df33bc..b13ebabe7578 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/autoUpload/AutoUploadWorker.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/autoUpload/AutoUploadWorker.kt @@ -321,6 +321,14 @@ class AutoUploadWorker( try { var (uploadEntity, upload) = createEntityAndUpload(user, localPath, remotePath) + + // if local file deleted, upload process cannot be started or retriable thus needs to be removed + if (path.isEmpty() || !file.exists()) { + Log_OC.w(TAG, "detected non-existing local file, removing entity") + deleteNonExistingFile(path, id, upload) + continue + } + try { // Insert/update to IN_PROGRESS state before starting upload val generatedId = uploadsStorageManager.uploadDao.insertOrReplace(uploadEntity) @@ -359,6 +367,12 @@ class AutoUploadWorker( "Exception during upload file, localPath: $localPath, remotePath: $remotePath," + " exception: $e" ) + + if (path.isEmpty() || !file.exists()) { + Log_OC.w(TAG, "detected non-existing local file, removing entity") + deleteNonExistingFile(path, id, upload) + continue + } } } catch (e: Exception) { Log_OC.e( @@ -366,14 +380,19 @@ class AutoUploadWorker( "Exception uploadFiles during creating entity and upload, localPath: $localPath, " + "remotePath: $remotePath, exception: $e" ) + } finally { + // update last id so upload can continue where it left + lastId = id } - - // update last id so upload can continue where it left - lastId = id } } } + private suspend fun deleteNonExistingFile(path: String, id: Int, upload: OCUpload) { + repository.deleteByLocalPathAndId(path, id) + uploadsStorageManager.removeUpload(upload) + } + private fun createEntityAndUpload(user: User, localPath: String, remotePath: String): Pair { val (needsCharging, needsWifi, uploadAction) = getUploadSettings(syncedFolder) Log_OC.d(TAG, "creating oc upload for ${user.accountName}") diff --git a/app/src/main/java/com/nextcloud/client/jobs/autoUpload/FileSystemRepository.kt b/app/src/main/java/com/nextcloud/client/jobs/autoUpload/FileSystemRepository.kt index 8cb6a74dc1ec..b322b1bc7fc4 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/autoUpload/FileSystemRepository.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/autoUpload/FileSystemRepository.kt @@ -28,6 +28,10 @@ class FileSystemRepository(private val dao: FileSystemDao, private val context: const val BATCH_SIZE = 50 } + suspend fun deleteByLocalPathAndId(path: String, id: Int) { + dao.deleteByLocalPathAndId(path, id) + } + suspend fun getFilePathsWithIds(syncedFolder: SyncedFolder, lastId: Int): List> { val syncedFolderId = syncedFolder.id.toString() Log_OC.d(TAG, "Fetching candidate files for syncedFolderId = $syncedFolderId") diff --git a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java index 9bafd4fe593c..f13c73704962 100644 --- a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java @@ -1283,10 +1283,32 @@ public void handleLocalBehaviour() { handleLocalBehaviour(temporalFile, expectedFile, originalFile, client); } + private void deleteNonExistingFile(File file) { + if (file.exists()) { + return; + } + + Log_OC.d(TAG, "deleting non-existing file from upload list and file list"); + + uploadsStorageManager.removeUpload(mOCUploadId); + + // some chunks can be uploaded and can still exists in db thus we have to remove it as well + getStorageManager().removeFile(mFile, true, true); + } + private void handleLocalBehaviour(File temporalFile, File expectedFile, File originalFile, OwnCloudClient client) { + + // only LOCAL_BEHAVIOUR_COPY not using original file + if (mLocalBehaviour != FileUploadWorker.LOCAL_BEHAVIOUR_COPY) { + // if file is not exists we should only delete from our app + deleteNonExistingFile(originalFile); + } + + Log_OC.d(TAG, "handling local behaviour for: " + originalFile.getName() + " behaviour: " + mLocalBehaviour); + switch (mLocalBehaviour) { case FileUploadWorker.LOCAL_BEHAVIOUR_DELETE: try { @@ -1305,6 +1327,9 @@ private void handleLocalBehaviour(File temporalFile, move(temporalFile, expectedFile); } catch (IOException e) { Log_OC.e(TAG, e.getMessage()); + + // handling non-existing file for local copy as well + deleteNonExistingFile(temporalFile); } } else if (originalFile != null) { try {