Esempio n. 1
0
def test_error(config, local_docs):
    """Test with a bad root ref. Also test skipping bad non-root refs.

    :param config: conftest fixture.
    :param local_docs: conftest fixture.
    """
    pytest.run(local_docs, ['git', 'checkout', '-b', 'a_good', 'master'])
    pytest.run(local_docs, ['git', 'checkout', '-b', 'c_good', 'master'])
    pytest.run(local_docs, ['git', 'checkout', '-b', 'b_broken', 'master'])
    local_docs.join('conf.py').write('master_doc = exception\n')
    pytest.run(local_docs, ['git', 'commit', '-am', 'Broken version.'])
    pytest.run(local_docs, ['git', 'checkout', '-b', 'd_broken', 'b_broken'])
    pytest.run(
        local_docs,
        ['git', 'push', 'origin', 'a_good', 'b_broken', 'c_good', 'd_broken'])

    versions = Versions(gather_git_info(str(local_docs), ['conf.py'], tuple(),
                                        tuple()),
                        sort=['alpha'])
    assert [r['name'] for r in versions.remotes
            ] == ['a_good', 'b_broken', 'c_good', 'd_broken', 'master']

    # Bad root ref.
    config.root_ref = 'b_broken'
    with pytest.raises(HandledError):
        pre_build(str(local_docs), versions)

    # Remove bad non-root refs.
    config.root_ref = 'master'
    pre_build(str(local_docs), versions)
    assert [r['name']
            for r in versions.remotes] == ['a_good', 'c_good', 'master']
Esempio n. 2
0
def test_dual(local_docs):
    """With two versions, one with master_doc defined.

    :param local_docs: conftest fixture.
    """
    pytest.run(local_docs, ['git', 'checkout', 'feature'])
    local_docs.join('conf.py').write('master_doc = "index"\n')
    local_docs.join('index.rst').write('Test\n'
                                       '====\n'
                                       '\n'
                                       'Sample documentation.\n')
    pytest.run(local_docs, ['git', 'add', 'conf.py', 'index.rst'])
    pytest.run(local_docs,
               ['git', 'commit', '-m', 'Adding docs with master_doc'])
    pytest.run(local_docs, ['git', 'push', 'origin', 'feature'])

    versions = Versions(
        gather_git_info(str(local_docs), ['conf.py'], tuple(), tuple()))
    assert len(versions) == 2

    # Run and verify directory.
    exported_root = py.path.local(pre_build(str(local_docs), versions))
    assert len(exported_root.listdir()) == 2
    assert exported_root.join(versions['master']['sha'],
                              'conf.py').read() == ''
    assert exported_root.join(versions['feature']['sha'],
                              'conf.py').read() == 'master_doc = "index"\n'

    # Verify versions root_dirs and master_docs.
    expected = ['feature/index', 'master/contents']
    assert sorted(
        posixpath.join(r['root_dir'], r['master_doc'])
        for r in versions.remotes) == expected
Esempio n. 3
0
def test_invalid_name(local_docs):
    """Test handling of branch names with invalid root_dir characters.

    :param local_docs: conftest fixture.
    """
    pytest.run(local_docs, ['git', 'checkout', '-b', 'robpol86/feature'])
    pytest.run(local_docs, ['git', 'push', 'origin', 'robpol86/feature'])

    versions = Versions(
        gather_git_info(str(local_docs), ['conf.py'], tuple(), tuple()))
    assert len(versions) == 2

    # Verify versions root_dirs and master_docs.
    pre_build(str(local_docs), versions)
    expected = ['master/contents', 'robpol86_feature/contents']
    assert sorted(
        posixpath.join(r['root_dir'], r['master_doc'])
        for r in versions.remotes) == expected
Esempio n. 4
0
def test_file_collision(local_docs):
    """Test handling of filename collisions between generates files from root and branch names.

    :param local_docs: conftest fixture.
    """
    pytest.run(local_docs, ['git', 'checkout', '-b', '_static'])
    pytest.run(local_docs, ['git', 'push', 'origin', '_static'])

    versions = Versions(
        gather_git_info(str(local_docs), ['conf.py'], tuple(), tuple()))
    assert len(versions) == 2

    # Verify versions root_dirs and master_docs.
    pre_build(str(local_docs), versions)
    expected = ['_static_/contents', 'master/contents']
    assert sorted(
        posixpath.join(r['root_dir'], r['master_doc'])
        for r in versions.remotes) == expected
Esempio n. 5
0
def test_single(local_docs):
    """With single version.

    :param local_docs: conftest fixture.
    """
    versions = Versions(
        gather_git_info(str(local_docs), ['conf.py'], tuple(), tuple()))
    assert len(versions) == 1

    # Run and verify directory.
    exported_root = py.path.local(pre_build(str(local_docs), versions))
    assert len(exported_root.listdir()) == 1
    assert exported_root.join(versions['master']['sha'],
                              'conf.py').read() == ''

    # Verify root_dir and master_doc..
    expected = ['master/contents']
    assert sorted(
        posixpath.join(r['root_dir'], r['master_doc'])
        for r in versions.remotes) == expected
Esempio n. 6
0
def build(config, rel_source, destination, **options):
    """Fetch branches/tags and build all locally.

    Just fetch all remote branches and tags, export them to a temporary directory, run
    sphinx-build on each one, and then store all built documentation in DESTINATION.

    REL_SOURCE is the path to the docs directory relative to the git root. If the source directory has moved around
    between git tags you can specify additional directories.

    DESTINATION is the path to the local directory that will hold all generated docs for all versions.

    To pass options to sphinx-build (run for every branch/tag) use a double hyphen
    (e.g. build docs docs/_build/html -- -D setting=value).
    \f

    :param sphinxcontrib.versioning.lib.Config config: Runtime configuration.
    :param tuple rel_source: Possible relative paths (to git root) of Sphinx directory containing conf.py (e.g. docs).
    :param str destination: Destination directory to copy/overwrite built docs to. Does not delete old files.
    :param dict options: Additional Click options.
    """
    if 'pre' in config:
        config.pop('pre')(rel_source)
        config.update({k: v for k, v in options.items() if v})
        if config.local_conf:
            config.update(read_local_conf(config.local_conf), ignore_set=True)
    if NO_EXECUTE:
        raise RuntimeError(config, rel_source, destination)
    log = logging.getLogger(__name__)

    # Gather git data.
    log.info('Gathering info about the remote git repository...')
    conf_rel_paths = [os.path.join(s, 'conf.py') for s in rel_source]
    remotes = gather_git_info(config.git_root, conf_rel_paths,
                              config.whitelist_branches, config.whitelist_tags)
    if not remotes:
        log.error('No docs found in any remote branch/tag. Nothing to do.')
        raise HandledError
    versions = Versions(
        remotes,
        sort=config.sort,
        priority=config.priority,
        invert=config.invert,
        pdf_file=config.pdf_file,
    )

    # Get root ref.
    if not override_root_main_ref(config, versions.remotes, False):
        log.error('Root ref %s not found in: %s', config.root_ref,
                  ' '.join(r[1] for r in remotes))
        raise HandledError
    log.info('Root ref is: %s', config.root_ref)

    # Get banner main ref.
    if not config.show_banner:
        config.update(dict(banner_greatest_tag=False,
                           banner_main_ref=None,
                           banner_recent_tag=False),
                      overwrite=True)
    elif not override_root_main_ref(config, versions.remotes, True):
        log.warning('Banner main ref %s not found in: %s',
                    config.banner_main_ref, ' '.join(r[1] for r in remotes))
        log.warning('Disabling banner.')
        config.update(dict(banner_greatest_tag=False,
                           banner_main_ref=None,
                           banner_recent_tag=False,
                           show_banner=False),
                      overwrite=True)
    else:
        log.info('Banner main ref is: %s', config.banner_main_ref)

    # Pre-build.
    log.info(
        "Pre-running Sphinx to collect versions' master_doc and other info.")
    exported_root = pre_build(config.git_root, versions)
    if config.banner_main_ref and config.banner_main_ref not in [
            r['name'] for r in versions.remotes
    ]:
        log.warning(
            'Banner main ref %s failed during pre-run. Disabling banner.',
            config.banner_main_ref)
        config.update(dict(banner_greatest_tag=False,
                           banner_main_ref=None,
                           banner_recent_tag=False,
                           show_banner=False),
                      overwrite=True)

    # Build.
    build_all(exported_root, destination, versions)

    # Cleanup.
    log.debug('Removing: %s', exported_root)
    shutil.rmtree(exported_root)

    # Store versions in state for push().
    config['versions'] = versions
def build(config, rel_source, destination, **options):
    """Fetch branches/tags and build all locally.

    Doesn't push anything to remote. Just fetch all remote branches and tags, export them to a temporary directory, run
    sphinx-build on each one, and then store all built documentation in DESTINATION.

    REL_SOURCE is the path to the docs directory relative to the git root. If the source directory has moved around
    between git tags you can specify additional directories.

    DESTINATION is the path to the local directory that will hold all generated docs for all versions.

    To pass options to sphinx-build (run for every branch/tag) use a double hyphen
    (e.g. build docs docs/_build/html -- -D setting=value).
    \f

    :param sphinxcontrib.versioning.lib.Config config: Runtime configuration.
    :param tuple rel_source: Possible relative paths (to git root) of Sphinx directory containing conf.py (e.g. docs).
    :param str destination: Destination directory to copy/overwrite built docs to. Does not delete old files.
    :param dict options: Additional Click options.
    """
    if 'pre' in config:
        config.pop('pre')(rel_source)
        config.update({k: v for k, v in options.items() if v})
        if config.local_conf:
            config.update(read_local_conf(config.local_conf), ignore_set=True)
    if NO_EXECUTE:
        raise RuntimeError(config, rel_source, destination)
    log = logging.getLogger(__name__)

    # Gather git data.
    log.info('Gathering info about the remote git repository...')
    conf_rel_paths = [os.path.join(s, 'conf.py') for s in rel_source]
    remotes = gather_git_info(config.git_root, conf_rel_paths, config.whitelist_branches, config.whitelist_tags)
    if not remotes:
        log.error('No docs found in any remote branch/tag. Nothing to do.')
        raise HandledError
    versions = Versions(
        remotes,
        sort=config.sort,
        priority=config.priority,
        invert=config.invert,
    )

    # Get root ref.
    if not override_root_main_ref(config, versions.remotes, False):
        log.error('Root ref %s not found in: %s', config.root_ref, ' '.join(r[1] for r in remotes))
        raise HandledError
    log.info('Root ref is: %s', config.root_ref)

    # Get banner main ref.
    if not config.show_banner:
        config.update(dict(banner_greatest_tag=False, banner_main_ref=None, banner_recent_tag=False), overwrite=True)
    elif not override_root_main_ref(config, versions.remotes, True):
        log.warning('Banner main ref %s not found in: %s', config.banner_main_ref, ' '.join(r[1] for r in remotes))
        log.warning('Disabling banner.')
        config.update(dict(banner_greatest_tag=False, banner_main_ref=None, banner_recent_tag=False, show_banner=False),
                      overwrite=True)
    else:
        log.info('Banner main ref is: %s', config.banner_main_ref)

    # Pre-build.
    log.info("Pre-running Sphinx to collect versions' master_doc and other info.")
    exported_root = pre_build(config.git_root, versions)
    if config.banner_main_ref and config.banner_main_ref not in [r['name'] for r in versions.remotes]:
        log.warning('Banner main ref %s failed during pre-run. Disabling banner.', config.banner_main_ref)
        config.update(dict(banner_greatest_tag=False, banner_main_ref=None, banner_recent_tag=False, show_banner=False),
                      overwrite=True)

    # Build.
    build_all(exported_root, destination, versions)

    # Cleanup.
    log.debug('Removing: %s', exported_root)
    shutil.rmtree(exported_root)

    # Store versions in state for push().
    config['versions'] = versions