|
3 | 3 | except ImportError: # pragma: no cover
|
4 | 4 | from asyncio import get_event_loop as get_running_loop # Python 3.6 compatibility
|
5 | 5 |
|
6 |
| -import re |
7 | 6 | import os
|
| 7 | +import re |
8 | 8 |
|
| 9 | +from ppadb import InstallError |
9 | 10 | from ppadb.command.transport_async import TransportAsync
|
10 | 11 | from ppadb.sync_async import SyncAsync
|
| 12 | +from ppadb.utils.logger import AdbLogging |
| 13 | + |
| 14 | +try: |
| 15 | + from shlex import quote as cmd_quote |
| 16 | +except ImportError: |
| 17 | + from pipes import quote as cmd_quote |
| 18 | + |
| 19 | + |
| 20 | +logger = AdbLogging.get_logger(__name__) |
| 21 | + |
11 | 22 |
|
12 | 23 |
|
13 | 24 | def _get_src_info(src):
|
@@ -60,10 +71,67 @@ async def push(self, src, dest, mode=0o644, progress=None):
|
60 | 71 |
|
61 | 72 | for item in files:
|
62 | 73 | await self._push(os.path.join(root, item), os.path.join(dest, root_dir_path, item), mode, progress)
|
63 |
| - |
| 74 | + |
64 | 75 | async def pull(self, src, dest):
|
65 | 76 | sync_conn = await self.sync()
|
66 | 77 | sync = SyncAsync(sync_conn)
|
67 | 78 |
|
68 | 79 | async with sync_conn:
|
69 | 80 | return await sync.pull(src, dest)
|
| 81 | + |
| 82 | + async def install(self, path, |
| 83 | + forward_lock=False, # -l |
| 84 | + reinstall=False, # -r |
| 85 | + test=False, # -t |
| 86 | + installer_package_name="", # -i {installer_package_name} |
| 87 | + shared_mass_storage=False, # -s |
| 88 | + internal_system_memory=False, # -f |
| 89 | + downgrade=False, # -d |
| 90 | + grand_all_permissions=False # -g |
| 91 | + ): |
| 92 | + dest = SyncAsync.temp(path) |
| 93 | + |
| 94 | + try: |
| 95 | + await self.push(path, dest) |
| 96 | + except Exception: |
| 97 | + raise InstallError("file transfer to device failed") |
| 98 | + |
| 99 | + parameters = [] |
| 100 | + if forward_lock: parameters.append("-l") |
| 101 | + if reinstall: parameters.append("-r") |
| 102 | + if test: parameters.append("-t") |
| 103 | + if len(installer_package_name) > 0: parameters.append("-i {}".format(installer_package_name)) |
| 104 | + if shared_mass_storage: parameters.append("-s") |
| 105 | + if internal_system_memory: parameters.append("-f") |
| 106 | + if downgrade: parameters.append("-d") |
| 107 | + if grand_all_permissions: parameters.append("-g") |
| 108 | + |
| 109 | + try: |
| 110 | + result = await self.shell( |
| 111 | + "pm install {} {}".format(" ".join(parameters), cmd_quote(dest)) |
| 112 | + ) |
| 113 | + match = re.search(self.INSTALL_RESULT_PATTERN, result) |
| 114 | + |
| 115 | + if match and match.group(1) == "Success": |
| 116 | + return True |
| 117 | + elif match: |
| 118 | + groups = match.groups() |
| 119 | + raise InstallError(dest, groups[1]) |
| 120 | + else: |
| 121 | + raise InstallError(dest, result) |
| 122 | + finally: |
| 123 | + await self.shell("rm -f {}".format(dest)) |
| 124 | + |
| 125 | + async def async_uninstall(self, package): |
| 126 | + result = await self.shell("pm uninstall {}".format(package)) |
| 127 | + |
| 128 | + m = re.search(self.UNINSTALL_RESULT_PATTERN, result) |
| 129 | + |
| 130 | + if m and m.group(1) == "Success": |
| 131 | + return True |
| 132 | + elif m: |
| 133 | + logger.error(m.group(1)) |
| 134 | + return False |
| 135 | + else: |
| 136 | + logger.error("There is no message after uninstalling") |
| 137 | + return False |
0 commit comments