Ejemplo n.º 1
0
async def send_to_remote(delta: Delta) -> None:
    """
    Send files to remote with adb push.
    adb is run in parallel to increase speed.
    This could be turned of by setting batch_size to 1
    NOTE: in order to actually preserve metadata, we have to send and touch the file.
    I hate you Android.
    """
    base_adb_command = make_adb_command('push')

    def run_cmd(file_stat: FileStat):
        source = file_stat.filename
        destination = delta.remote_path / file_stat.relname
        adb_command = [*base_adb_command, source, destination.as_posix()]
        return run_adb_command(adb_command)

    with bar(len(delta.upload),
             f'INFO:{__name__}:Pushing files to remote') as progress:
        for chunk in chunks(delta.upload, config.adb_batch_size):
            send_queue = map(run_cmd, chunk)
            send_result = await asyncio.gather(*send_queue)
            filtered_chunk = [
                stat for stat, (errored, _) in zip(chunk, send_result)
                if not errored
            ]

            await touch_files(delta, filtered_chunk)
            progress.update(config.adb_batch_size)
Ejemplo n.º 2
0
async def del_remote(delta: Delta) -> None:
    """Delete files from remote with the rm command"""
    with bar(len(delta.remove),
             f'INFO:{__name__}:Deleting remote files') as progress:
        base_adb_command = make_adb_command('shell')
        for chunk in chunks(delta.remove, config.command_batch_size):
            adb_command = [
                *base_adb_command, 'rm', '-r',
                *[shlex.quote(file_stat.filename) for file_stat in chunk]
            ]
            await run_adb_command(adb_command)
            progress.update(config.command_batch_size)
Ejemplo n.º 3
0
async def touch_files(delta: Delta, chunk: List[FileStat]) -> List[str]:
    """Creates a very long list of adb shell + touch command. should be more efficient"""
    base_adb_command = make_adb_command('shell')

    def generate_cmd(file_stat: FileStat):
        destination = delta.remote_path / file_stat.relname
        return [
            'touch', '-cmd',
            shlex.quote(
                datetime.fromtimestamp(
                    file_stat.mtime).strftime('%Y-%m-%d%H:%M:%S')),
            shlex.quote(destination.as_posix()), ';'
        ]

    adb_command = [
        *base_adb_command, *chain.from_iterable(map(generate_cmd, chunk))
    ]
    await run_adb_command(adb_command)
Ejemplo n.º 4
0
async def send_to_local(delta: Delta) -> None:
    """Pull files from remote to local"""
    base_adb_command = [*make_adb_command('pull'), '-a']

    def run_cmd(file_stat: FileStat):
        source = file_stat.filename
        destination = delta.local_path / file_stat.relname
        # mkdir parent path just in case because adb on Windows will error
        destination.parent.mkdir(parents=True, exist_ok=True)
        adb_command = [*base_adb_command, source, str(destination)]
        return run_adb_command(adb_command)

    with bar(len(delta.upload),
             f'INFO:{__name__}:Pulling files to local') as progress:
        for chunk in chunks(delta.upload, config.adb_batch_size):
            send_queue = map(run_cmd, chunk)
            await asyncio.gather(*send_queue)
            progress.update(config.adb_batch_size)
Ejemplo n.º 5
0
async def get_remote_files(path: str,
                           max_depth: int = 1,
                           output_dict: FileStatDict = {}) -> FileStatDict:
    """
    This uses find. May not be available in most systems, but I don't care.
    Updated to use find and stat seperately with chunking to reduce overhead
    """
    base_adb_command = make_adb_command('shell')
    adb_command = [
        *base_adb_command, 'find', path, '-type', 'f', '-maxdepth',
        str(max_depth)
    ]
    log_adb_command(adb_command)

    errored, find_output = await run_adb_command(adb_command,
                                                 combine=False,
                                                 bypass_dry_run=True)
    if errored:
        raise Exception('Unable to run find command on remote')

    find_output = find_output.splitlines()
    with bar(len(find_output),
             f'INFO:{__name__}:Creating remote file list') as slider:
        for find_slice in chunks(find_output, config.command_batch_size):
            adb_command = [
                *base_adb_command, 'stat', '-c', '%N:%s:%Y',
                *map(shlex.quote, find_slice)
            ]
            log_adb_command(adb_command)

            errored, output = await run_adb_command(adb_command,
                                                    combine=False,
                                                    bypass_dry_run=True)
            if not errored:
                for line in output.splitlines():
                    file_stat = RemoteFileStat(path, line, ':')
                    output_dict[file_stat.relname] = file_stat
            slider.update(config.command_batch_size)

    return output_dict