@operation(pipeline_facts={
    'find_files': 'destination'
})
def sync(state, host, source, destination, user=None, group=None, mode=None, delete=False):

    # If we don't enforce the source ending with /, remote_dirname below might start with
    # a /, which makes the path.join cut off the destination bit.
    if not source.endswith(path.sep):
        source = '{0}{1}'.format(source, path.sep)

    # Source relative to deploy.py
    if state.deploy_dir:
        source = path.join(state.deploy_dir, source)

    put_files = []
    ensure_dirnames = []
    for dirname, _, filenames in walk(source):
        remote_dirname = dirname.replace(source, '')

        if remote_dirname:
            ensure_dirnames.append(remote_dirname)

        for filename in filenames:
            put_files.append((
                path.join(dirname, filename),
                path.join(destination, remote_dirname, filename)
            ))

    commands = []

    # Ensure the destination directory
    commands.extend(directory(
        state, host, destination,
        user=user, group=group
    ))

    # Ensure any remote dirnames
    for dirname in ensure_dirnames:
        commands.extend(directory(
            state, host,
            '{0}/{1}'.format(destination, dirname),
            user=user, group=group
        ))

    # Put each file combination
    for local_filename, remote_filename in put_files:
        commands.extend(put(
            state, host,
            local_filename, remote_filename,
            user=user, group=group, mode=mode,
            add_deploy_dir=False
        ))

    # Delete any extra files
    if delete:
        remote_filenames = set(host.fact.find_files(destination) or [])
        wanted_filenames = set([remote_filename for _, remote_filename in put_files])
        files_to_delete = remote_filenames - wanted_filenames
        for filename in files_to_delete:
            commands.extend(file(filename, present=False))

    return commands
Test the ability to retrieve the branches in a repository.
dataset/ETHPy150Open Fizzadar/pyinfra/pyinfra/modules/files.py/sync--crossover with--dataset/ETHPy150Open sigmavirus24/github3.py/tests/integration/test_repos_repo.py/TestRepository.test_branches