Improve finding restore sets

now that we store more things in the same folder
This commit is contained in:
Torsten Grote 2021-02-16 16:18:45 -03:00 committed by Chirayu Desai
parent 5b2b75047e
commit fa123f07a0

View file

@ -24,6 +24,9 @@ internal class DocumentsProviderRestorePlugin(
override val fullRestorePlugin: FullRestorePlugin override val fullRestorePlugin: FullRestorePlugin
) : RestorePlugin { ) : RestorePlugin {
private val tokenRegex = Regex("([0-9]{13})") // good until the year 2286
private val chunkFolderRegex = Regex("[a-f0-9]{2}")
@Throws(IOException::class) @Throws(IOException::class)
override suspend fun hasBackup(uri: Uri): Boolean { override suspend fun hasBackup(uri: Uri): Boolean {
val parent = DocumentFile.fromTreeUri(context, uri) ?: throw AssertionError() val parent = DocumentFile.fromTreeUri(context, uri) ?: throw AssertionError()
@ -59,18 +62,21 @@ internal class DocumentsProviderRestorePlugin(
return backupSets return backupSets
} }
for (set in files) { for (set in files) {
// retrieve name only once as this causes a DB query
val name = set.name
// get current token from set or continue to next file/set // get current token from set or continue to next file/set
val token = set.getTokenOrNull() ?: continue val token = set.getTokenOrNull(name) ?: continue
// block until children of set are available // block until children of set are available
val metadata = try { val metadata = try {
set.findFileBlocking(context, FILE_BACKUP_METADATA) set.findFileBlocking(context, FILE_BACKUP_METADATA)
} catch (e: IOException) { } catch (e: IOException) {
Log.e(TAG, "Error reading metadata file in backup set folder: ${set.name}", e) Log.e(TAG, "Error reading metadata file in backup set folder: $name", e)
null null
} }
if (metadata == null) { if (metadata == null) {
Log.w(TAG, "Missing metadata file in backup set folder: ${set.name}") Log.w(TAG, "Missing metadata file in backup set folder: $name")
} else { } else {
backupSets.add(BackupSet(token, metadata)) backupSets.add(BackupSet(token, metadata))
} }
@ -78,21 +84,29 @@ internal class DocumentsProviderRestorePlugin(
return backupSets return backupSets
} }
private fun DocumentFile.getTokenOrNull(): Long? { private fun DocumentFile.getTokenOrNull(name: String?): Long? {
if (!isDirectory || name == null) { val looksLikeToken = name != null && tokenRegex.matches(name)
if (name != FILE_NO_MEDIA) { // check for isDirectory only if we already have a valid token (causes DB query)
if (!looksLikeToken || !isDirectory) {
// only log unexpected output
if (name != null && isUnexpectedFile(name)) {
Log.w(TAG, "Found invalid backup set folder: $name") Log.w(TAG, "Found invalid backup set folder: $name")
} }
return null return null
} }
return try { return try {
name!!.toLong() name?.toLong()
} catch (e: NumberFormatException) { } catch (e: NumberFormatException) {
Log.w(TAG, "Found invalid backup set folder: $name") throw AssertionError(e)
null
} }
} }
private fun isUnexpectedFile(name: String): Boolean {
return name != FILE_NO_MEDIA &&
!chunkFolderRegex.matches(name) &&
!name.endsWith(".SeedSnap")
}
@Throws(IOException::class) @Throws(IOException::class)
override suspend fun getApkInputStream( override suspend fun getApkInputStream(
token: Long, token: Long,