mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-07-29 07:13:11 +00:00
Refactor zip import/export using Path
This commit is contained in:
parent
840084d2c9
commit
72b67ab5d4
@ -35,7 +35,6 @@ import org.schabi.newpipe.streams.io.StoredFileHelper;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.ZipHelper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
@ -61,13 +60,12 @@ public class BackupRestoreSettingsFragment extends BasePreferenceFragment {
|
||||
@Override
|
||||
public void onCreatePreferences(@Nullable final Bundle savedInstanceState,
|
||||
@Nullable final String rootKey) {
|
||||
final File homeDir = ContextCompat.getDataDir(requireContext());
|
||||
Objects.requireNonNull(homeDir);
|
||||
manager = new ImportExportManager(new BackupFileLocator(homeDir));
|
||||
final var dbDir = Objects.requireNonNull(ContextCompat.getDataDir(requireContext()))
|
||||
.toPath();
|
||||
manager = new ImportExportManager(new BackupFileLocator(dbDir));
|
||||
|
||||
importExportDataPathKey = getString(R.string.import_export_data_path);
|
||||
|
||||
|
||||
addPreferencesFromResourceRegistry();
|
||||
|
||||
final Preference importDataPreference = requirePreference(R.string.import_data);
|
||||
@ -183,9 +181,7 @@ public class BackupRestoreSettingsFragment extends BasePreferenceFragment {
|
||||
}
|
||||
|
||||
try {
|
||||
if (!manager.ensureDbDirectoryExists()) {
|
||||
throw new IOException("Could not create databases dir");
|
||||
}
|
||||
manager.ensureDbDirectoryExists();
|
||||
|
||||
// replace the current database
|
||||
if (!manager.extractDb(file)) {
|
||||
|
@ -1,11 +1,12 @@
|
||||
package org.schabi.newpipe.settings.export
|
||||
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.div
|
||||
|
||||
/**
|
||||
* Locates specific files of NewPipe based on the home directory of the app.
|
||||
*/
|
||||
class BackupFileLocator(private val homeDir: File) {
|
||||
class BackupFileLocator(homeDir: Path) {
|
||||
companion object {
|
||||
const val FILE_NAME_DB = "newpipe.db"
|
||||
@Deprecated(
|
||||
@ -16,13 +17,9 @@ class BackupFileLocator(private val homeDir: File) {
|
||||
const val FILE_NAME_JSON_PREFS = "preferences.json"
|
||||
}
|
||||
|
||||
val dbDir by lazy { File(homeDir, "/databases") }
|
||||
|
||||
val db by lazy { File(dbDir, FILE_NAME_DB) }
|
||||
|
||||
val dbJournal by lazy { File(dbDir, "$FILE_NAME_DB-journal") }
|
||||
|
||||
val dbShm by lazy { File(dbDir, "$FILE_NAME_DB-shm") }
|
||||
|
||||
val dbWal by lazy { File(dbDir, "$FILE_NAME_DB-wal") }
|
||||
val dbDir = homeDir / "databases"
|
||||
val db = homeDir / FILE_NAME_DB
|
||||
val dbJournal = homeDir / "$FILE_NAME_DB-journal"
|
||||
val dbShm = dbDir / "$FILE_NAME_DB-shm"
|
||||
val dbWal = dbDir / "$FILE_NAME_DB-wal"
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ import java.io.FileNotFoundException
|
||||
import java.io.IOException
|
||||
import java.io.ObjectOutputStream
|
||||
import java.util.zip.ZipOutputStream
|
||||
import kotlin.io.path.createDirectories
|
||||
import kotlin.io.path.deleteExisting
|
||||
|
||||
class ImportExportManager(private val fileLocator: BackupFileLocator) {
|
||||
companion object {
|
||||
@ -28,11 +30,8 @@ class ImportExportManager(private val fileLocator: BackupFileLocator) {
|
||||
// previous file size, the file will retain part of the previous content and be corrupted
|
||||
ZipOutputStream(SharpOutputStream(file.openAndTruncateStream()).buffered()).use { outZip ->
|
||||
// add the database
|
||||
ZipHelper.addFileToZip(
|
||||
outZip,
|
||||
BackupFileLocator.FILE_NAME_DB,
|
||||
fileLocator.db.path,
|
||||
)
|
||||
val name = BackupFileLocator.FILE_NAME_DB
|
||||
ZipHelper.addFileToZip(outZip, name, fileLocator.db)
|
||||
|
||||
// add the legacy vulnerable serialized preferences (will be removed in the future)
|
||||
ZipHelper.addFileToZip(
|
||||
@ -61,11 +60,10 @@ class ImportExportManager(private val fileLocator: BackupFileLocator) {
|
||||
|
||||
/**
|
||||
* Tries to create database directory if it does not exist.
|
||||
*
|
||||
* @return Whether the directory exists afterwards.
|
||||
*/
|
||||
fun ensureDbDirectoryExists(): Boolean {
|
||||
return fileLocator.dbDir.exists() || fileLocator.dbDir.mkdir()
|
||||
@Throws(IOException::class)
|
||||
fun ensureDbDirectoryExists() {
|
||||
fileLocator.dbDir.createDirectories()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -75,16 +73,13 @@ class ImportExportManager(private val fileLocator: BackupFileLocator) {
|
||||
* @return true if the database was successfully extracted, false otherwise
|
||||
*/
|
||||
fun extractDb(file: StoredFileHelper): Boolean {
|
||||
val success = ZipHelper.extractFileFromZip(
|
||||
file,
|
||||
BackupFileLocator.FILE_NAME_DB,
|
||||
fileLocator.db.path,
|
||||
)
|
||||
val name = BackupFileLocator.FILE_NAME_DB
|
||||
val success = ZipHelper.extractFileFromZip(file, name, fileLocator.db)
|
||||
|
||||
if (success) {
|
||||
fileLocator.dbJournal.delete()
|
||||
fileLocator.dbWal.delete()
|
||||
fileLocator.dbShm.delete()
|
||||
fileLocator.dbJournal.deleteExisting()
|
||||
fileLocator.dbWal.deleteExisting()
|
||||
fileLocator.dbShm.deleteExisting()
|
||||
}
|
||||
|
||||
return success
|
||||
|
@ -6,12 +6,12 @@ import org.schabi.newpipe.streams.io.StoredFileHelper;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
@ -55,17 +55,17 @@ public final class ZipHelper {
|
||||
|
||||
|
||||
/**
|
||||
* This function helps to create zip files. Caution this will overwrite the original file.
|
||||
* This function helps to create zip files. Caution, this will overwrite the original file.
|
||||
*
|
||||
* @param outZip the ZipOutputStream where the data should be stored in
|
||||
* @param nameInZip the path of the file inside the zip
|
||||
* @param fileOnDisk the path of the file on the disk that should be added to zip
|
||||
* @param path the path of the file on the disk that should be added to zip
|
||||
*/
|
||||
public static void addFileToZip(final ZipOutputStream outZip,
|
||||
final String nameInZip,
|
||||
final String fileOnDisk) throws IOException {
|
||||
try (FileInputStream fi = new FileInputStream(fileOnDisk)) {
|
||||
addFileToZip(outZip, nameInZip, fi);
|
||||
final Path path) throws IOException {
|
||||
try (var inputStream = Files.newInputStream(path)) {
|
||||
addFileToZip(outZip, nameInZip, inputStream);
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,33 +113,18 @@ public final class ZipHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* This will extract data from ZipInputStream. Caution this will overwrite the original file.
|
||||
* This will extract data from ZipInputStream. Caution, this will overwrite the original file.
|
||||
*
|
||||
* @param zipFile the zip file to extract from
|
||||
* @param nameInZip the path of the file inside the zip
|
||||
* @param fileOnDisk the path of the file on the disk where the data should be extracted to
|
||||
* @param path the path of the file on the disk where the data should be extracted to
|
||||
* @return will return true if the file was found within the zip file
|
||||
*/
|
||||
public static boolean extractFileFromZip(final StoredFileHelper zipFile,
|
||||
final String nameInZip,
|
||||
final String fileOnDisk) throws IOException {
|
||||
return extractFileFromZip(zipFile, nameInZip, input -> {
|
||||
// delete old file first
|
||||
final File oldFile = new File(fileOnDisk);
|
||||
if (oldFile.exists()) {
|
||||
if (!oldFile.delete()) {
|
||||
throw new IOException("Could not delete " + fileOnDisk);
|
||||
}
|
||||
}
|
||||
|
||||
final byte[] data = new byte[BUFFER_SIZE];
|
||||
try (FileOutputStream outFile = new FileOutputStream(fileOnDisk)) {
|
||||
int count;
|
||||
while ((count = input.read(data)) != -1) {
|
||||
outFile.write(data, 0, count);
|
||||
}
|
||||
}
|
||||
});
|
||||
final Path path) throws IOException {
|
||||
return extractFileFromZip(zipFile, nameInZip, input ->
|
||||
Files.copy(input, path, StandardCopyOption.REPLACE_EXISTING));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -10,7 +10,9 @@ import org.schabi.newpipe.streams.io.StoredFileHelper
|
||||
import us.shandian.giga.io.FileStream
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.nio.file.Files
|
||||
import kotlin.io.path.createTempFile
|
||||
import kotlin.io.path.exists
|
||||
import kotlin.io.path.fileSize
|
||||
|
||||
class ImportAllCombinationsTest {
|
||||
|
||||
@ -47,10 +49,10 @@ class ImportAllCombinationsTest {
|
||||
BackupFileLocator::class.java,
|
||||
Mockito.withSettings().stubOnly()
|
||||
)
|
||||
val db = File.createTempFile("newpipe_", "")
|
||||
val dbJournal = File.createTempFile("newpipe_", "")
|
||||
val dbWal = File.createTempFile("newpipe_", "")
|
||||
val dbShm = File.createTempFile("newpipe_", "")
|
||||
val db = createTempFile("newpipe_", "")
|
||||
val dbJournal = createTempFile("newpipe_", "")
|
||||
val dbWal = createTempFile("newpipe_", "")
|
||||
val dbShm = createTempFile("newpipe_", "")
|
||||
Mockito.`when`(fileLocator.db).thenReturn(db)
|
||||
Mockito.`when`(fileLocator.dbJournal).thenReturn(dbJournal)
|
||||
Mockito.`when`(fileLocator.dbShm).thenReturn(dbShm)
|
||||
@ -62,7 +64,7 @@ class ImportAllCombinationsTest {
|
||||
Assert.assertFalse(dbJournal.exists())
|
||||
Assert.assertFalse(dbWal.exists())
|
||||
Assert.assertFalse(dbShm.exists())
|
||||
Assert.assertTrue("database file size is zero", Files.size(db.toPath()) > 0)
|
||||
Assert.assertTrue("database file size is zero", db.fileSize() > 0)
|
||||
}
|
||||
} else {
|
||||
runTest {
|
||||
@ -70,7 +72,7 @@ class ImportAllCombinationsTest {
|
||||
Assert.assertTrue(dbJournal.exists())
|
||||
Assert.assertTrue(dbWal.exists())
|
||||
Assert.assertTrue(dbShm.exists())
|
||||
Assert.assertEquals(0, Files.size(db.toPath()))
|
||||
Assert.assertEquals(0, db.fileSize())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,8 +25,14 @@ import org.schabi.newpipe.streams.io.StoredFileHelper
|
||||
import us.shandian.giga.io.FileStream
|
||||
import java.io.File
|
||||
import java.io.ObjectInputStream
|
||||
import java.nio.file.Files
|
||||
import java.util.zip.ZipFile
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.io.path.createTempDirectory
|
||||
import kotlin.io.path.createTempFile
|
||||
import kotlin.io.path.deleteIfExists
|
||||
import kotlin.io.path.exists
|
||||
import kotlin.io.path.fileSize
|
||||
import kotlin.io.path.inputStream
|
||||
|
||||
@RunWith(MockitoJUnitRunner::class)
|
||||
class ImportExportManagerTest {
|
||||
@ -46,7 +52,7 @@ class ImportExportManagerTest {
|
||||
|
||||
@Test
|
||||
fun `The settings must be exported successfully in the correct format`() {
|
||||
val db = File(classloader.getResource("settings/newpipe.db")!!.file)
|
||||
val db = Path(classloader.getResource("settings/newpipe.db")!!.file)
|
||||
`when`(fileLocator.db).thenReturn(db)
|
||||
|
||||
val expectedPreferences = mapOf("such pref" to "much wow")
|
||||
@ -81,8 +87,8 @@ class ImportExportManagerTest {
|
||||
|
||||
@Test
|
||||
fun `Ensuring db directory existence must work`() {
|
||||
val dir = Files.createTempDirectory("newpipe_").toFile()
|
||||
Assume.assumeTrue(dir.delete())
|
||||
val dir = createTempDirectory("newpipe_")
|
||||
Assume.assumeTrue(dir.deleteIfExists())
|
||||
`when`(fileLocator.dbDir).thenReturn(dir)
|
||||
|
||||
ImportExportManager(fileLocator).ensureDbDirectoryExists()
|
||||
@ -91,7 +97,7 @@ class ImportExportManagerTest {
|
||||
|
||||
@Test
|
||||
fun `Ensuring db directory existence must work when the directory already exists`() {
|
||||
val dir = Files.createTempDirectory("newpipe_").toFile()
|
||||
val dir = createTempDirectory("newpipe_")
|
||||
`when`(fileLocator.dbDir).thenReturn(dir)
|
||||
|
||||
ImportExportManager(fileLocator).ensureDbDirectoryExists()
|
||||
@ -100,10 +106,10 @@ class ImportExportManagerTest {
|
||||
|
||||
@Test
|
||||
fun `The database must be extracted from the zip file`() {
|
||||
val db = File.createTempFile("newpipe_", "")
|
||||
val dbJournal = File.createTempFile("newpipe_", "")
|
||||
val dbWal = File.createTempFile("newpipe_", "")
|
||||
val dbShm = File.createTempFile("newpipe_", "")
|
||||
val db = createTempFile("newpipe_", "")
|
||||
val dbJournal = createTempFile("newpipe_", "")
|
||||
val dbWal = createTempFile("newpipe_", "")
|
||||
val dbShm = createTempFile("newpipe_", "")
|
||||
`when`(fileLocator.db).thenReturn(db)
|
||||
`when`(fileLocator.dbJournal).thenReturn(dbJournal)
|
||||
`when`(fileLocator.dbShm).thenReturn(dbShm)
|
||||
@ -117,15 +123,15 @@ class ImportExportManagerTest {
|
||||
assertFalse(dbJournal.exists())
|
||||
assertFalse(dbWal.exists())
|
||||
assertFalse(dbShm.exists())
|
||||
assertTrue("database file size is zero", Files.size(db.toPath()) > 0)
|
||||
assertTrue("database file size is zero", db.fileSize() > 0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Extracting the database from an empty zip must not work`() {
|
||||
val db = File.createTempFile("newpipe_", "")
|
||||
val dbJournal = File.createTempFile("newpipe_", "")
|
||||
val dbWal = File.createTempFile("newpipe_", "")
|
||||
val dbShm = File.createTempFile("newpipe_", "")
|
||||
val db = createTempFile("newpipe_", "")
|
||||
val dbJournal = createTempFile("newpipe_", "")
|
||||
val dbWal = createTempFile("newpipe_", "")
|
||||
val dbShm = createTempFile("newpipe_", "")
|
||||
`when`(fileLocator.db).thenReturn(db)
|
||||
|
||||
val emptyZip = File(classloader.getResource("settings/nodb_noser_nojson.zip")?.file!!)
|
||||
@ -136,7 +142,7 @@ class ImportExportManagerTest {
|
||||
assertTrue(dbJournal.exists())
|
||||
assertTrue(dbWal.exists())
|
||||
assertTrue(dbShm.exists())
|
||||
assertEquals(0, Files.size(db.toPath()))
|
||||
assertEquals(0, db.fileSize())
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
x
Reference in New Issue
Block a user