def lister(op, sess, stem: str = None, put_team: str = None): """ list matching repos optionally, add to specified EXISTING team """ if put_team and not gb.team_exists(op, put_team): raise ValueError(f"Team {put_team} does not exist in {op.login}") # %% get user / organization handle userorg = gb.user_or_org(sess, op.login) # %% prepare to loop over repos repos = gb.get_repos(userorg) to_act: T.Iterable[github.Repository.Repository] if stem: to_act = (repo for repo in repos if repo.name.startswith(stem)) else: to_act = repos for repo in to_act: teams = repo.get_teams() if teams.totalCount == 0: if put_team: print(repo.name, "=>", put_team) team = op.get_team_by_slug(put_team) team.add_to_repos(repo) else: print(repo.name)
def main(oauth: Path, orgname: str, stem: str): # %% authentication user, sess = gb.connect(oauth) assert isinstance(user, github.AuthenticatedUser.AuthenticatedUser ), "unwatch is for users only, not orgs" gb.check_api_limit(sess) # %% get organization handle org = gb.user_or_org(sess, orgname) # %% prepare to loop over repos repos = gb.get_repos(org) to_act = [ repo for repo in repos if user.has_in_watched(repo) and repo.name.startswith(stem) ] if not to_act: raise SystemExit( f"There were no repos left to unwatch with {stem} in {orgname}") print("\ntype affirmative to UNWATCH", "\n".join([repo.full_name for repo in to_act])) if input() != "affirmative": raise SystemExit("Aborted") for repo in to_act: user.remove_from_watched(repo) print("UnWatched:", repo.full_name)
def main(): p = ArgumentParser( description="Set Private GitHub repos for a user/organization with repo names matching pattern" ) p.add_argument("userorgname", help="GitHub username / organizations") p.add_argument("oauth", help="Oauth filename") p.add_argument("pattern", help="make private repos with name starting with this string") P = p.parse_args() # %% authentication sess = gb.session(P.oauth) gb.check_api_limit(sess) # %% get user / organization handle userorg = gb.user_or_org(sess, P.userorgname) # %% prepare to loop over repos repos = gb.get_repos(userorg) to_act = [repo for repo in repos if repo.name.startswith(P.pattern) and not repo.private] if not to_act: raise SystemExit( f"There were no repos left to make private with {P.pattern} in {P.userorgname}" ) print("\ntype affirmative to make PRIVATE", "\n".join([repo.full_name for repo in to_act])) if input() != "affirmative": raise SystemExit("Aborted") for repo in to_act: repo.edit(private=True) print("private:", repo.full_name)
def main(): p = ArgumentParser(description="List user/organization repos") p.add_argument("user", help="Git remote username / organization name") p.add_argument("oauth", help="Oauth filename", nargs="?") p.add_argument("-p", "--pattern", help="only repos with name starting with this string") p.add_argument("-settings", help="open settings page for each repo", action="store_true") p.add_argument("-alerts", help="open alerts page for each repo", action="store_true") P = p.parse_args() # %% authentication sess = gb.session(P.oauth) gb.check_api_limit(sess) # %% get user / organization handle userorg = gb.user_or_org(sess, P.user) # %% prepare to loop over repos repos = gb.get_repos(userorg) if P.pattern: repos = (repo for repo in repos if repo.name.startswith(P.pattern)) for repo in repos: print(repo.full_name) if P.settings: webbrowser.open_new_tab("https://github.com/" + repo.full_name + "/settings") if P.alerts: webbrowser.open_new_tab("https://github.com/" + repo.full_name + "/network/alerts")
def test_get_repos(): try: userorg = pgu.user_or_org(pgu.session(), OK_username) repos = pgu.get_repos(userorg) except (ConnectionRefusedError, gexc.RateLimitExceededException): pytest.skip("GitHub API limit exceeded") assert len(list(repos)) > 0
def main(username: str, oauth: str, stem: str): # %% authentication sess = gb.session(P.oauth) gb.check_api_limit(sess) # %% get user / organization handle userorg = gb.user_or_org(sess, P.user) # %% prepare to loop over repos repos = gb.get_repos(userorg) to_act = (repo for repo in repos if repo.name.startswith(stem) and not repo.archived) for repo in to_act: print(repo.full_name)
def main(): p = ArgumentParser(description='Set all collaborator permission to "read"') p.add_argument("user", help="GitHub username / organizations") p.add_argument("oauth", help="Oauth filename") p.add_argument("pattern", help="modify repos with name starting with this string") p.add_argument("--omit", help="dont consider these admins", nargs="+") P = p.parse_args() # %% authentication sess = gb.session(P.oauth) gb.check_api_limit(sess) # %% get user / organization handle userorg = gb.user_or_org(sess, P.user) # %% prepare to loop over repos repos = gb.get_repos(userorg) to_modify = [repo for repo in repos if repo.name.startswith(P.pattern)] print( "\ntype affirmative to remove all collaborators from\n", "\n".join([repo.full_name for repo in to_modify]), ) modify = input() == "affirmative" for repo in to_modify: gb.check_api_limit(sess) collabs = repo.get_collaborators() admins = [c.login for c in collabs if c.login not in P.omit] if not admins: continue print("admins", repo.full_name, " ".join(admins)) if modify: if repo.archived: logging.error( f"could not remove collabs from archived {repo.full_name}") webbrowser.open_new_tab("https://github.com/" + repo.full_name + "/settings") continue for admin in admins: repo.remove_from_collaborators(admin)
def main(username: str, oauth: str, stem: str): # %% authentication sess = gb.session(P.oauth) gb.check_api_limit(sess) # %% get user / organization handle userorg = gb.user_or_org(sess, P.user) # %% prepare to loop over repos repos = gb.get_repos(userorg) # filter repos to_act = (repo for repo in repos if repo.name.startswith(stem) and repo.name != ".github" and not repo.fork and not repo.archived and repo.owner.login == userorg.login) for repo in to_act: try: repo.get_license() except github.GithubException: print(repo.full_name)
def main(user: str, oauth: Path, pattern: str, only_empty: bool) -> typing.List[str]: # %% authentication sess = gb.session(oauth) gb.check_api_limit(sess) # %% get user / organization handle userorg = gb.user_or_org(sess, user) # %% prepare to loop over repos repos = gb.get_repos(userorg) to_act = (repo for repo in repos if repo.name.startswith(pattern)) empty: typing.List[str] = [] for repo in to_act: print(f"examining {repo.name}", end="\r") authors: typing.Dict[str, int] = {} try: for commit in repo.get_commits(): if only_empty: break if not commit.stats: # GitHub API bug? continue if commit.stats.total == 0: continue if not commit.author: # GitHub API bug? continue if commit.author.login in authors: authors[commit.author.login] += commit.stats.total else: authors[commit.author.login] = commit.stats.total if not only_empty: ax = figure().gca() ax.scatter(authors.keys(), authors.values()) ax.get_yaxis().get_major_formatter().set_useOffset(False) ax.set_ylabel("total LoC changed") ax.set_yscale("log") ax.set_title(repo.name) except github.GithubException as exc: if "empty" in exc.data["message"]: empty.append(repo.name) print() # flush stdout \r return sorted(empty)
def main(): p = ArgumentParser(description="mass copy files by language") p.add_argument("copyfn", help="file to copy into repos") p.add_argument("targetfn", help="path to copy file into in repos") p.add_argument("language", help="coding language to consider (case-sensitive)") p.add_argument("oauth", help="Oauth file") p.add_argument("userorg", help="Github Username or Organization") p.add_argument("-stem", help="beginning of repo names", default="") P = p.parse_args() language = P.language copyfn = Path(P.copyfn).expanduser().resolve(True) copy_text = copyfn.read_text() target = P.targetfn sess = gb.session(P.oauth) gb.check_api_limit(sess) # %% get user / organization handle userorg = gb.user_or_org(sess, P.userorg) # %% prepare to loop over repos repos = gb.get_repos(userorg) to_act = (repo for repo in repos if repo.name.startswith(P.stem)) for repo in to_act: # sometimes a large amount of HTML, CSS, or docs show up as first language. langs = repo.get_languages() if not langs.get(language): continue try: existing = repo.get_contents(target) existing_code = base64.b64decode(existing.content).decode("utf8") if existing_code.strip() != copy_text.strip(): print(repo.full_name, "different from", copyfn) repo.update_file(target, "update CI", copy_text, existing.sha) except github.GithubException: # file not exist on remote print("copying", copyfn, "to", target, "in", repo.full_name) repo.create_file(target, "init CI", copy_text)
def test_bad_username(): with pytest.raises(ValueError): pgu.user_or_org(pgu.session(), random_username)