Beispiel #1
0
def version_wrapper() -> str:
    from util import spawn_process
    git_tag = spawn_process('git tag --points-at HEAD')[1]
    worktree_flag = spawn_process('git diff-index --quiet HEAD')[0]
    worktree_status = '-dirty' if worktree_flag != 0 else ''
    if len(git_tag) > 0:
        return git_tag + worktree_status
    else:
        git_branch = spawn_process('git rev-parse --abbrev-ref HEAD')[1]
        git_hash = spawn_process('git rev-parse --short HEAD')[1]
        git_time = spawn_process('git show -s --format=%cI HEAD')[1]
        return f'{git_branch}-{git_hash}-{git_time}{worktree_status}'
 def _create_remote_dir(self, path: str):
     args = ['adb', 'shell', 'mkdir', "'%s'" % path.replace("'", "'\"'\"'")]
     stdout, stderr = spawn_process(args, 'utf8')
     if stderr.rstrip('\r\n').endswith('No such file or directory'):
         # recursive mode
         if path == '/':
             raise RuntimeError(stderr)
         self._create_remote_dir(self._abs_path(path + '/..'))
         # retry after parent dir created
         stdout, stderr = spawn_process(args, 'utf8')
         if len(stderr) > 0:
             raise RuntimeError(stderr)
 def _remove_remote(path: str):
     stdout, stderr = spawn_process([
         'adb', 'shell', 'rm', '-rf',
         "'%s'" % path.replace("'", "'\"'\"'")
     ], 'utf8')
     if len(stderr) > 0:
         raise RuntimeError(stderr)
    def _adb_stat(self, path: str, retry_count: int = 5) -> FileMeta:
        if retry_count == 0:
            raise RuntimeError(
                'Adb repeatedly returned empty stat result for path %s' % path)
        # escape char (') in linux shell
        path_escaped = path.replace("'", "'\"'\"'")
        stdout, stderr = spawn_process([
            'adb', 'shell', 'stat', '-L', '-c', "'%A/%s/%X/%Y/%W/%n'",
            "'%s'" % path_escaped
        ], 'utf8')
        if len(stderr) > 0:
            raise RuntimeError(stderr)
        if len(stdout) == 0:  # unknown reason for stat returns nothing
            return self._adb_stat(path, retry_count - 1)
        parts = stdout.rstrip('\r\n').split('/')

        def _cvt_ts(x):
            return 0 if x == '?' else int(x)

        # debug
        try:
            return FileMeta(
                path_id=0,
                file_name=parts[-1],
                file_size=int(parts[1]),
                access_time=datetime.datetime.fromtimestamp(_cvt_ts(parts[2])),
                mod_time=datetime.datetime.fromtimestamp(_cvt_ts(parts[3])),
                create_time=datetime.datetime.fromtimestamp(_cvt_ts(parts[4])),
                is_dir=int(parts[0][0] == 'd'))
        except IndexError:
            warn('Invalid scheme: "%s" for path "%s"' % (stdout, path))
            raise
Beispiel #5
0
 def send_click(self, x: float, y: float, stay_time: float = 0.1):
     px, py = self._translate_normalized_coord(x, y)
     stdout = _handle_adb_ipc_output(
         spawn_process([
             self._adb, 'shell',
             'input touchscreen swipe %d %d %d %d %d' %
             (px, py, px, py, int(round(stay_time * 1000)))
         ]))
     if len(stdout) > 0:
         logger.debug('Adb output: %s' % stdout)
 def __init__(self,
              path: str,
              thread_count: int = 4,
              max_history_backup: int = 30):
     if not os.path.exists(path):
         os.makedirs(path, exist_ok=True)
     assert os.path.isdir(path), 'path must be a directory'
     assert thread_count > 0, 'thread_count must be positive'
     assert max_history_backup > 0, 'max_history_backup must be positive'
     self._path = path
     self._sql_file = os.path.join(self._path, 'entries.db')
     if not os.path.isfile(self._sql_file):
         open(self._sql_file, 'wb').close()
     self._sql_conn = SqliteAccessor(self._sql_file)
     # creating repository directory
     for i in range(256):
         os.makedirs(os.path.join(self._path, 'objects', '%02x' % i),
                     exist_ok=True)
     spawn_process('adb start-server', 'utf8')
     self._thread_count = thread_count
     self._max_history_backup = max_history_backup
 def _push_file(self, path: str, meta: FileMeta):
     local_path = os.path.join(self._path, 'objects',
                               '%02x' % meta.sha256[0], meta.sha256.hex())
     if os.path.exists(local_path):
         os.utime(local_path, (get_datetime_timestamp(
             meta.access_time), get_datetime_timestamp(meta.mod_time)))
         stdout, stderr = spawn_process(['adb', 'push', local_path, path],
                                        'utf8')
         if len(stderr) > 0:
             raise RuntimeError(stderr)
     else:
         warn("Could not push file %s: object %s not found" %
              (path, local_path))
Beispiel #8
0
 def __init__(self,
              adb_executable: Optional[str] = None,
              crop_16_9: bool = True):
     self._adb = None
     if adb_executable is not None:
         assert os.path.isfile(
             adb_executable
         ), 'Adb (Android Debug Bridge) executable not exists'
         self._adb = adb_executable
     else:
         candidate_paths = list(sys.path)
         candidate_paths.extend(os.getenv('PATH').split(os.pathsep))
         for path in candidate_paths:
             candidate_file = os.path.join(path, 'adb.exe')
             if os.path.isfile(candidate_file):
                 self._adb = candidate_file
                 break
         if self._adb is None:
             raise RuntimeError(
                 'Could not find adb.exe in PATH, please specify it by parameter'
             )
         logger.info('Found adb.exe in %s' % self._adb)
     # spawn_process([self._adb, 'kill-server'])
     spawn_process([self._adb, 'start-server'])
     thd = threading.Thread(target=self._shutdown_adb_server,
                            daemon=False,
                            name='Adb server shutdown thread')
     thd.start()
     self._crop_16_9 = False
     self._device_screen_size = self._get_screenshot_internal().shape
     logger.debug('Device resolution: %s' %
                  str(self._device_screen_size[1::-1]))
     self._crop_16_9 = crop_16_9
     w = self._device_screen_size[0] / 9.0 * 16.0
     beg_x = int(round(self._device_screen_size[1] - w) / 2)
     self._16_9_screen_slice_x = slice(beg_x, beg_x + int(round(w)))
 def _pull_file(self, path: str, meta: FileMeta):
     local_path = os.path.join(
         self._path, 'tmp_adb_pull_file_%d' % threading.get_ident())
     try:
         open(local_path, 'wb').close()
         stdout, stderr = spawn_process(['adb', 'pull', path, local_path],
                                        'utf8')
         if len(stderr) > 0:
             raise RuntimeError(stderr)
         if stdout.startswith("adb: error:"):
             raise RuntimeError(stdout)
         with open(local_path, 'rb') as f:
             md5_hash = hashlib.md5()
             sha256_hash = hashlib.sha256()
             while True:
                 b = f.read(4096)
                 if len(b) == 0:
                     break
                 md5_hash.update(b)
                 sha256_hash.update(b)
             meta.md5 = md5_hash.digest()
             meta.sha256 = sha256_hash.digest()
         dest_path = os.path.join(self._path,
                                  'objects', '%02x' % meta.sha256[0],
                                  meta.sha256.hex())
         if not os.path.exists(dest_path):
             shutil.move(local_path, dest_path)
         else:
             st_dest = os.stat(dest_path)
             st_src = os.stat(local_path)
             if st_dest.st_size == st_src.st_size:
                 os.remove(local_path)
             else:
                 raise RuntimeError(
                     'Hash conflict for object %s (path: %s)' %
                     (meta.sha256.hex(), path))
         db_meta = self._sql_conn.select(FileMeta,
                                         1,
                                         path_id=meta.path_id,
                                         file_name=meta.file_name)
         if db_meta is None:
             self._sql_conn.insert(meta)
         elif meta != db_meta:
             self._sql_conn.update(meta)
     except FileNotFoundError:
         warn('Could not pull file: %s' % path)
Beispiel #10
0
 def send_slide(self,
                p_from: Tuple[float, float],
                p_to: Tuple[float, float],
                stay_time_before_move: float = 0.1,
                stay_time_move: float = 0.8,
                stay_time_after_move: float = 0.1):
     p1 = self._translate_normalized_coord(*p_from)
     p2 = self._translate_normalized_coord(*p_to)
     if not self.__warn_func_disabled:
         self.__warn_func_disabled = True
         logger.warning(
             'Param stay_time_before_move and stay_time_after_move is disabled for Adb attacher'
         )
     stdout = _handle_adb_ipc_output(
         spawn_process([
             'adb', 'shell',
             'input touchscreen swipe %d %d %d %d %d' %
             (p1[0], p1[1], p2[0], p2[1], int(round(stay_time_move * 1000)))
         ]))
     if len(stdout) > 0:
         logger.debug('Adb output: %s' % stdout)
 def _adb_ls(path: str,
             retry_count: int = 5) -> Tuple[List[str], List[str]]:
     if retry_count == 0:
         raise RuntimeError(
             'Adb repeatedly returned empty ls result for path %s' % path)
     if not path.endswith('/'):
         path = path + '/'
     # escape char (') in linux shell
     path = path.replace("'", "'\"'\"'")
     stdout, stderr = spawn_process(
         ['adb', 'shell', 'ls', '-al',
          "'%s'" % path], 'utf8')
     if len(stderr) > 0:
         raise RuntimeError(stderr)
     if len(stdout) == 0:
         return BackupManager._adb_ls(path, retry_count - 1)
     dirs = []
     files = []
     for line in stdout.split('\n'):
         if len(line) == 0:
             continue
         match = re.match(ls_al_pattern, line)
         if match is None:
             continue
         # '\ ' will be used in newest android OS
         filename = match.group('name').replace('\\', '')
         permission = match.group('permission')
         if filename == '.' or filename == '..':
             continue
         if permission[0] == 'd':
             dirs.append(filename)
         elif permission[0] == '-':
             files.append(filename)
         else:
             print('Unsupported file permission attribute:', permission)
     return dirs, files