mirror of
https://github.com/mvt-project/mvt.git
synced 2026-10-30 09:46:25 +01:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd8434cc16 | ||
|
|
1ad80d4864 | ||
|
|
6491857bb1 | ||
|
|
fbd001298b |
No files matched your search
+4
-1
@@ -323,7 +323,10 @@ def check_backup(
|
|||||||
cmd.list_modules()
|
cmd.list_modules()
|
||||||
return
|
return
|
||||||
|
|
||||||
log.info("Checking iTunes backup located at: %s", backup_path)
|
if not cmd.resolve_backup_path():
|
||||||
|
ctx.exit(1)
|
||||||
|
|
||||||
|
log.info("Checking iTunes backup located at: %s", cmd.target_path)
|
||||||
|
|
||||||
cmd.run()
|
cmd.run()
|
||||||
cmd.show_alerts_brief()
|
cmd.show_alerts_brief()
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
# https://license.mvt.re/1.1/
|
# https://license.mvt.re/1.1/
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from mvt.common.command import Command
|
from mvt.common.command import Command
|
||||||
@@ -16,6 +17,12 @@ from .modules.mixed import MIXED_MODULES
|
|||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def is_ios_backup_folder(path: str) -> bool:
|
||||||
|
return os.path.isfile(os.path.join(path, "Manifest.db")) and os.path.isfile(
|
||||||
|
os.path.join(path, "Info.plist")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CmdIOSCheckBackup(Command):
|
class CmdIOSCheckBackup(Command):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -52,5 +59,46 @@ class CmdIOSCheckBackup(Command):
|
|||||||
self.name = "check-backup"
|
self.name = "check-backup"
|
||||||
self.modules = BACKUP_MODULES + MIXED_MODULES
|
self.modules = BACKUP_MODULES + MIXED_MODULES
|
||||||
|
|
||||||
|
def resolve_backup_path(self) -> bool:
|
||||||
|
target_path = getattr(self, "target_path", None)
|
||||||
|
if not isinstance(target_path, str) or not target_path:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if is_ios_backup_folder(target_path):
|
||||||
|
return True
|
||||||
|
|
||||||
|
if not os.path.isdir(target_path):
|
||||||
|
self.log.critical(
|
||||||
|
"%s does not appear to be an iTunes backup folder. "
|
||||||
|
"Expected Manifest.db and Info.plist.",
|
||||||
|
target_path,
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
candidates = []
|
||||||
|
for entry_name in sorted(os.listdir(target_path)):
|
||||||
|
entry_path = os.path.join(target_path, entry_name)
|
||||||
|
if os.path.isdir(entry_path) and is_ios_backup_folder(entry_path):
|
||||||
|
candidates.append(entry_path)
|
||||||
|
|
||||||
|
if len(candidates) == 1:
|
||||||
|
self.log.info("Found iTunes backup in subfolder: %s", candidates[0])
|
||||||
|
self.target_path = candidates[0]
|
||||||
|
return True
|
||||||
|
|
||||||
|
if candidates:
|
||||||
|
self.log.critical(
|
||||||
|
"Found multiple iTunes backups in %s. Please specify one backup folder.",
|
||||||
|
target_path,
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.log.critical(
|
||||||
|
"%s does not appear to be an iTunes backup folder. "
|
||||||
|
"Expected Manifest.db and Info.plist.",
|
||||||
|
target_path,
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
def module_init(self, module):
|
def module_init(self, module):
|
||||||
module.is_backup = True
|
module.is_backup = True
|
||||||
@@ -3,6 +3,8 @@
|
|||||||
# Use of this software is governed by the MVT License 1.1 that can be found at
|
# Use of this software is governed by the MVT License 1.1 that can be found at
|
||||||
# https://license.mvt.re/1.1/
|
# https://license.mvt.re/1.1/
|
||||||
|
|
||||||
|
import shutil
|
||||||
|
|
||||||
from click.testing import CliRunner
|
from click.testing import CliRunner
|
||||||
|
|
||||||
from mvt.ios.cli import check_backup
|
from mvt.ios.cli import check_backup
|
||||||
@@ -16,3 +18,18 @@ class TestCheckBackupCommand:
|
|||||||
path = get_ios_backup_folder()
|
path = get_ios_backup_folder()
|
||||||
result = runner.invoke(check_backup, [path])
|
result = runner.invoke(check_backup, [path])
|
||||||
assert result.exit_code == 0
|
assert result.exit_code == 0
|
||||||
|
|
||||||
|
def test_check_finds_backup_in_subfolder(self, tmp_path, caplog):
|
||||||
|
runner = CliRunner()
|
||||||
|
backup_path = tmp_path / "MobileSync" / "Backup" / "device-id"
|
||||||
|
shutil.copytree(get_ios_backup_folder(), backup_path)
|
||||||
|
|
||||||
|
result = runner.invoke(check_backup, [str(backup_path.parent)])
|
||||||
|
assert result.exit_code == 0
|
||||||
|
assert f"Found iTunes backup in subfolder: {backup_path}" in caplog.text
|
||||||
|
|
||||||
|
def test_check_rejects_non_backup_folder(self, tmp_path, caplog):
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(check_backup, [str(tmp_path)])
|
||||||
|
assert result.exit_code == 1
|
||||||
|
assert "does not appear to be an iTunes backup folder" in caplog.text
|
||||||
@@ -63,6 +63,8 @@ def test_load_module_appears_only_for_supported_cli_command(tmp_path):
|
|||||||
|
|
||||||
|
|
||||||
def test_module_option_runs_supported_custom_module(tmp_path):
|
def test_module_option_runs_supported_custom_module(tmp_path):
|
||||||
|
(tmp_path / "Manifest.db").touch()
|
||||||
|
(tmp_path / "Info.plist").touch()
|
||||||
module_path = _write_custom_module(
|
module_path = _write_custom_module(
|
||||||
tmp_path / "custom.py",
|
tmp_path / "custom.py",
|
||||||
"CustomRunModule",
|
"CustomRunModule",
|
||||||
|
|||||||
Reference in new issue
Block a user