Ejemplo n.º 1
0
def _create_push_tuples(
    teams: List[plug.Team],
    template_repos: Iterable[plug.TemplateRepo],
    api: plug.PlatformAPI,
) -> Iterable[Tuple[bool, PushSpec]]:
    """Create push tuples for newly created repos. Repos that already exist are
    ignored.

    Args:
        teams: An iterable of teams.
        template_repos: Template repositories.
        api: A platform API instance.
    Returns:
        A list of tuples (created, push_tuple) for all student repo urls
        that relate to any of the master repo urls. ``created`` indicates
        whether or not the student repo was created in this invocation.
    """
    for team, template_repo in itertools.product(teams, template_repos):
        repo_name = plug.generate_repo_name(team, template_repo.name)
        created, repo = _create_or_fetch_repo(
            name=repo_name,
            description=f"{repo_name} created for {team.name}",
            private=True,
            team=team,
            api=api,
        )

        yield created, PushSpec(
            local_path=template_repo.path,
            repo_url=api.insert_auth(repo.url),
            branch=git.active_branch(template_repo.path),
            metadata=dict(repo=repo, team=team),
        )
Ejemplo n.º 2
0
def _create_update_push_tuples(
    teams: Iterable[plug.StudentTeam],
    template_repos: Iterable[plug.TemplateRepo],
    api: plug.PlatformAPI,
) -> Iterable[PushSpec]:
    """Create push tuples for existing repos. Repos that don't exist are
    ignored.

    Args:
        teams: An iterable of teams.
        template_repos: Template repositories.
        api: A platform API instance.
    Returns:
        A list of PushSpec namedtuples for all student repo urls that relate to
        any of the master repo urls.
    """
    urls_to_templates = {}
    for team, template_repo in itertools.product(teams, template_repos):
        repo_url, *_ = api.get_repo_urls(
            [template_repo.name], team_names=[team.name]
        )
        urls_to_templates[repo_url] = template_repo

    for repo in api.get_repos(list(urls_to_templates.keys())):
        template = urls_to_templates[repo.url]
        branch = git.active_branch(template.path)
        yield PushSpec(template.path, api.insert_auth(repo.url), branch)
Ejemplo n.º 3
0
def _push_to_platform(student_repos: List[plug.StudentRepo],
                      api: plug.PlatformAPI) -> None:
    push_tuples = [
        _repobee.git.Push(repo.path, api.insert_auth(repo.url),
                          _DEFAULT_BRANCH) for repo in student_repos
    ]
    _repobee.git.push(push_tuples)
Ejemplo n.º 4
0
def _try_insert_auth(repo: Union[plug.TemplateRepo, plug.StudentRepo],
                     api: plug.PlatformAPI) -> str:
    """Try to insert authentication into the URL."""
    try:
        return api.insert_auth(repo.url)
    except plug.InvalidURL:
        return repo.url
Ejemplo n.º 5
0
def _update_local_repos(local: List[plug.StudentRepo],
                        api: plug.PlatformAPI) -> None:
    expected_basedir = local[0].path.parent.parent
    assert all(
        map(lambda repo: repo.path.parent.parent == expected_basedir, local))
    specs = [
        CloneSpec(repo_url=api.insert_auth(repo.url), dest=repo.path)
        for repo in local
    ]
    # TODO figure out what to do when a local update fails
    clone(specs)
Ejemplo n.º 6
0
def migrate_repos(
    template_repo_urls: plug.types.SizedIterable[str], api: plug.PlatformAPI
) -> None:
    """Migrate a repository from an arbitrary URL to the target organization.
    The new repository is added to the master_repos team, which is created if
    it does not already exist.

    Args:
        template_repo_urls: Local urls to repos to migrate.
        api: An implementation of :py:class:`repobee_plug.PlatformAPI` used to
            interface with the platform (e.g. GitHub or GitLab) instance.
    """
    local_templates = [
        plug.TemplateRepo(name=urlutil.extract_repo_name(url), url=url)
        for url in template_repo_urls
    ]
    create_repo_it = plug.cli.io.progress_bar(
        (
            _create_or_fetch_repo(
                local.name, description="", private=True, api=api
            )
            for local in local_templates
        ),
        desc="Creating remote repos",
        total=len(template_repo_urls),
    )
    with tempfile.TemporaryDirectory() as tmpdir:
        workdir = pathlib.Path(tmpdir)
        _clone_all(local_templates, cwd=workdir, api=api)

        remote_templates = [
            plug.TemplateRepo(
                name=repo.name, url=repo.url, _path=workdir / repo.name
            )
            for _, repo in create_repo_it
        ]

        git.push(
            [
                PushSpec(
                    local_path=template_repo.path,
                    repo_url=api.insert_auth(template_repo.url),
                    branch=git.active_branch(template_repo.path),
                )
                for template_repo in remote_templates
            ]
        )

    plug.echo("Done!")
Ejemplo n.º 7
0
def clone_student_repos(
    repos: List[plug.StudentRepo],
    clone_dir: pathlib.Path,
    update_local: bool,
    api: plug.PlatformAPI,
) -> Iterable[Tuple[CloneStatus, plug.StudentRepo]]:
    assert all(map(lambda r: r.path is not None, repos))
    local = [repo for repo in repos if repo.path.exists()]
    if local and update_local:
        _update_local_repos(local, api)
    elif local and not update_local:
        _warn_local_repos(local)

    non_local = [repo for repo in repos if not repo.path.exists()]
    plug.log.info(f"Cloning into {non_local}")
    non_local_specs = [
        CloneSpec(
            dest=clone_dir / plug.fileutils.hash_path(repo.path),
            repo_url=api.insert_auth(repo.url),
            metadata=dict(repo=repo),
        )
        for repo in non_local
    ]

    failed_specs = clone(non_local_specs)

    failed_repos = {spec.metadata["repo"] for spec in failed_specs}
    success_repos = {repo for repo in non_local if repo not in failed_repos}

    for repo in success_repos:
        shutil.copytree(
            src=clone_dir / plug.fileutils.hash_path(repo.path), dst=repo.path
        )

    return (
        [(CloneStatus.EXISTED, repo) for repo in local]
        + [(CloneStatus.CLONED, repo) for repo in success_repos]
        + [(CloneStatus.FAILED, repo) for repo in failed_repos]
    )
Ejemplo n.º 8
0
def _get_authed_url(assignment_name: str, org_name: str,
                    api: plug.PlatformAPI) -> str:
    # FIXME temporary workaround as insert_auth is not implemented
    # in FakeAPI.get_repo_urls. Should be fixed in RepoBee 3.4.
    return api.insert_auth(
        api.get_repo_urls([assignment_name], org_name=org_name)[0])