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)
def _delete_anonymous_repos( assignment_names: Iterable[str], student_teams: Iterable[plug.StudentTeam], double_blind_key: str, api: plug.PlatformAPI, ): """Delete any anonymous repos created for these students and assignments. """ anon_repo_names = [ _hash_if_key( plug.generate_repo_name(student_team, assignment_name), key=double_blind_key, ) for student_team, assignment_name in itertools.product( student_teams, assignment_names) ] anon_repo_urls = api.get_repo_urls(anon_repo_names) anon_repos = api.get_repos(anon_repo_urls) anon_repos_progress = plug.cli.io.progress_bar( anon_repos, desc="Deleting anonymous repo copies", total=len(anon_repo_names), ) for repo in anon_repos_progress: api.delete_repo(repo) progresswrappers.end_progress(anon_repos_progress)
def post_setup(self, repo: plug.StudentRepo, api: plug.PlatformAPI): """Add a created student repo to the teachers team.""" platform_repo = next(iter(api.get_repos([repo.url]))) teachers_team = _get_or_create_team(TEACHERS_TEAM_NAME, api) api.assign_repo( team=teachers_team, repo=platform_repo, permission=plug.TeamPermission.PULL, ) return plug.Result( name="tamanager", status=plug.Status.SUCCESS, msg=f"Added to the {TEACHERS_TEAM_NAME} team", )
def command(self, api: plug.PlatformAPI) -> Optional[plug.Result]: teachers_team = _get_or_create_team(TEACHERS_TEAM_NAME, api) existing_members = teachers_team.members new_members = list(set(self.teachers) - set(existing_members)) api.assign_members(teachers_team, new_members, permission=plug.TeamPermission.PULL) for repo in plug.cli.io.progress_bar( api.get_repos(), desc="Granting read access to repos"): api.assign_repo( repo=repo, team=teachers_team, permission=plug.TeamPermission.PULL, ) msg = (f"Added {', '.join(new_members)} to the '{TEACHERS_TEAM_NAME}' " "team") return plug.Result(name="add-teachers", status=plug.Status.SUCCESS, msg=msg)
def get_repos( repo_urls: Iterable[str], api: plug.PlatformAPI, desc: str = "Fetching repos", **kwargs: Any, ) -> Iterable[plug.Repo]: """Wrapper around :py:meth:`repobee_plug.PlatformAPI.get_repos` that also provides an auto-updating progress bar to the CLI. Args: repo_urls: An iterable of repo URLs. api: An instance of the platform API. desc: A description of the action. kwargs: Keyword arguments to the underlying implementation of the progress bar. Returns: An iterable of repos with an auto-updating CLI progress bar. """ repo_urls = list(repo_urls) return plug.cli.io.progress_bar(api.get_repos(repo_urls), desc=desc, total=len(repo_urls), **kwargs)
def list_issues( repos: Iterable[plug.StudentRepo], api: plug.PlatformAPI, state: plug.IssueState = plug.IssueState.OPEN, title_regex: str = "", show_body: bool = False, author: Optional[str] = None, ) -> Mapping[str, List[plug.Result]]: """List all issues in the specified repos. Args: repos: The repos from which to fetch issues. api: An implementation of :py:class:`repobee_plug.PlatformAPI` used to interface with the platform (e.g. GitHub or GitLab) instance. state: state of the repo (open or closed). Defaults to open. title_regex: If specified, only issues with titles matching the regex are displayed. Defaults to the empty string (which matches everything). show_body: If True, the body of the issue is displayed along with the default info. author: Only show issues by this author. """ # TODO optimize by not getting all repos at once repos = list(repos) repo_names = [repo.name for repo in repos] max_repo_name_length = max(map(len, repo_names)) platform_repos = api.get_repos([repo.url for repo in repos]) issues_per_repo = _get_issue_generator( platform_repos, title_regex=title_regex, author=author, state=state, api=api, ) # _log_repo_issues exhausts the issues_per_repo iterator and # returns a list with the same information. It's important to # have issues_per_repo as an iterator as it greatly speeds # up visual feedback to the user when fetching many issues pers_issues_per_repo = _log_repo_issues( issues_per_repo, show_body, max_repo_name_length + 6 ) # for writing to JSON hook_result_mapping = { repo_name: [ plug.Result( name="list-issues", status=plug.Status.SUCCESS, msg="Fetched {} issues from {}".format(len(issues), repo_name), data={issue.number: issue.to_dict() for issue in issues}, ) ] for repo_name, issues in pers_issues_per_repo } # meta hook result hook_result_mapping["list-issues"] = [ plug.Result( name="meta", status=plug.Status.SUCCESS, msg="Meta info about the list-issues hook results", data={"state": state.value}, ) ] return hook_result_mapping