@@ -13,9 +13,11 @@ import android.os.Build
1313import android.provider.MediaStore
1414import com.nextcloud.client.database.dao.FileSystemDao
1515import com.nextcloud.client.database.entity.FilesystemEntity
16+ import com.nextcloud.client.database.entity.UploadEntity
1617import com.nextcloud.utils.extensions.shouldSkipFile
1718import com.owncloud.android.datamodel.SyncedFolder
1819import com.owncloud.android.datamodel.UploadsStorageManager
20+ import com.owncloud.android.datamodel.UploadsStorageManager.UploadStatus
1921import com.owncloud.android.db.OCUpload
2022import com.owncloud.android.lib.common.utils.Log_OC
2123import com.owncloud.android.utils.SyncedFolderUtils
@@ -200,11 +202,19 @@ class FileSystemRepository(
200202
201203 val fileModified = (lastModified ? : file.lastModified())
202204 val hasNotChanged = entity?.fileModified == fileModified
203- val fileSentForUpload = entity?.fileSentForUpload == 1
205+ var fileSentForUpload = entity?.fileSentForUpload == 1
204206
205- if (hasNotChanged && fileSentForUpload) {
206- Log_OC .d(TAG , " File hasn't changed since last scan. skipping: $localPath " )
207- return
207+ if (entity != null && hasNotChanged && fileSentForUpload) {
208+ if (wasUploadFinished(entity, syncedFolder, localPath, file)) {
209+ Log_OC .d(TAG , " File hasn't changed since last scan. skipping: $localPath " )
210+ return
211+ }
212+
213+ Log_OC .w(TAG , " marked as sent but upload never finished, queueing again: $localPath " )
214+ deleteUnfinishedUpload(entity, syncedFolder, localPath, file)
215+
216+ // the upload never finished, so the checks below must not skip it as an already handled old file
217+ fileSentForUpload = false
208218 }
209219
210220 if (syncedFolder.shouldSkipFile(file, fileModified, creationTime, fileSentForUpload)) {
@@ -232,6 +242,50 @@ class FileSystemRepository(
232242 }
233243 }
234244
245+ private fun wasUploadFinished (
246+ entity : FilesystemEntity ,
247+ syncedFolder : SyncedFolder ,
248+ localPath : String ,
249+ file : File
250+ ): Boolean {
251+ val upload = getUpload(entity, syncedFolder, localPath, file) ? : return true
252+
253+ return upload.status == UploadStatus .UPLOAD_SUCCEEDED .value ||
254+ upload.status == UploadStatus .UPLOAD_CANCELLED .value
255+ }
256+
257+ private fun deleteUnfinishedUpload (
258+ entity : FilesystemEntity ,
259+ syncedFolder : SyncedFolder ,
260+ localPath : String ,
261+ file : File
262+ ) {
263+ val remotePath = getUpload(entity, syncedFolder, localPath, file)?.remotePath ? : return
264+
265+ uploadsStorageManager.uploadDao.deleteByRemotePathAndAccountName(
266+ remotePath = remotePath,
267+ accountName = syncedFolder.account
268+ )
269+
270+ Log_OC .d(TAG , " deleted unfinished upload record of remotePath: $remotePath " )
271+ }
272+
273+ private fun getUpload (
274+ entity : FilesystemEntity ,
275+ syncedFolder : SyncedFolder ,
276+ localPath : String ,
277+ file : File
278+ ): UploadEntity ? {
279+ // the entity keeps the path the worker used
280+ val remotePath = entity.remotePath ? : syncFolderHelper.getAutoUploadRemotePath(syncedFolder, file)
281+
282+ return uploadsStorageManager.uploadDao.getUploadByAccountAndPaths(
283+ accountName = syncedFolder.account,
284+ localPath = localPath,
285+ remotePath = remotePath
286+ )
287+ }
288+
235289 private fun getFileChecksum (file : File ): Long? = try {
236290 file.inputStream().use { fis ->
237291 val crc = CRC32 ()
0 commit comments