def main():
    try:
        try:
            run()
        except codetools.DogpileError as e:
            error(e)
            n = len(e.errors)
            sys.exit(n if n < 256 else 255)
        else:
            sys.exit(0)
        finally:
            if 'g' in globals():
                pygithub.debug_ratelimit(g)
    except SystemExit as e:
        debug("exit {status}".format(status=str(e)))
        raise e
Пример #2
0
def main():
    try:
        try:
            run()
        except codetools.DogpileError as e:
            error(e)
            n = len(e.errors)
            sys.exit(n if n < 256 else 255)
        else:
            sys.exit(0)
        finally:
            if 'g' in globals():
                pygithub.debug_ratelimit(g)
    except SystemExit as e:
        debug("exit {status}".format(status=str(e)))
        raise e
Пример #3
0
def run():
    args = parse_args()

    codetools.setup_logging(args.debug)

    global g
    g = pygithub.login_github(token_path=args.token_path, token=args.token)

    # protect destination org
    codetools.validate_org(args.dst_org)
    src_org = g.get_organization(args.src_org)
    dst_org = g.get_organization(args.dst_org)
    info("forking repos from: {org}".format(org=src_org.login))
    info("                to: {org}".format(org=dst_org.login))

    debug('looking for repos -- this can take a while for large orgs...')
    if args.team:
        debug('checking that selection team(s) exist')
        try:
            org_teams = list(src_org.get_teams())
        except github.RateLimitExceededException:
            raise
        except github.GithubException as e:
            msg = 'error getting teams'
            raise pygithub.CaughtOrganizationError(src_org, e, msg) from None

        missing_teams = [n for n in args.team if n not in
                         [t.name for t in org_teams]]
        if missing_teams:
            error("{n} team(s) do not exist:".format(n=len(missing_teams)))
            [error("  '{t}'".format(t=n)) for n in missing_teams]
            return
        fork_teams = [t for t in org_teams if t.name in args.team]
        repos = pygithub.get_repos_by_team(fork_teams)
        debug('selecting repos by membership in team(s):')
        [debug("  '{t}'".format(t=t.name)) for t in fork_teams]
    else:
        repos = pygithub.get_repos_by_team(fork_teams)

    src_repos = list(itertools.islice(repos, args.limit))

    repo_count = len(src_repos)
    if not repo_count:
        debug('nothing to do -- exiting')
        return

    debug("found {n} repos to be forked from org {src_org}:".format(
        n=repo_count,
        src_org=src_org.login
    ))
    [debug("  {r}".format(r=r.full_name)) for r in src_repos]

    if args.copy_teams:
        debug('checking source repo team membership...')
        # dict of repo and team objects, keyed by repo name
        src_rt = find_teams_by_repo(src_repos)

        # extract a non-duplicated list of team names from all repos being
        # forked as a dict, keyed by team name
        src_teams = find_used_teams(src_rt)

        debug('found {n} teams in use within org {o}:'.format(
            n=len(src_teams),
            o=src_org.login
        ))
        [debug("  '{t}'".format(t=t)) for t in src_teams.keys()]

        # check for conflicting teams in dst org before attempting to create
        # any forks so its possible to bail out before any resources have been
        # created.
        debug('checking teams in destination org')
        conflicting_teams = pygithub.get_teams_by_name(
            dst_org,
            list(src_teams.keys())
        )
        if conflicting_teams:
            raise TeamError(
                "found {n} conflicting teams in {o}: {teams}".format(
                    n=len(conflicting_teams),
                    o=dst_org.login,
                    teams=[t.name for t in conflicting_teams]
                ))

    debug('there is no spoon...')
    problems = []
    pygithub.debug_ratelimit(g)
    dst_repos, skipped_repos, err = create_forks(
        dst_org,
        src_repos,
        fail_fast=args.fail_fast,
        dry_run=args.dry_run
    )
    if err:
        problems += err

    if args.copy_teams:
        # filter out repos which were skipped
        # dict of str(fork_repo.name): fork_repo
        dst_forks = dict((r.name, r) for r in dst_repos)
        bad_repos = dict((r.name, r) for r in skipped_repos)
        # dict of str(team.name): [repos] to be created
        dst_teams = {}
        for name, repos in src_teams.items():
            dst_teams[name] = [dst_forks[r.name] for r in repos
                               if r.name not in bad_repos]

        _, err = create_teams(
            dst_org,
            dst_teams,
            with_repos=True,
            fail_fast=args.fail_fast,
            dry_run=args.dry_run
        )
        if err:
            problems += err

    if problems:
        msg = "{n} errors forking repo(s)/teams(s)".format(
            n=len(problems))
        raise codetools.DogpileError(problems, msg)
Пример #4
0
def create_teams(
    org,
    teams,
    with_repos=False,
    ignore_existing=False,
    fail_fast=False,
    dry_run=False
):
    assert isinstance(org, github.Organization.Organization), type(org)
    assert isinstance(teams, dict), type(teams)

    # it takes fewer api calls to create team(s) with an explicit list of
    # members after all repos have been forked but this blows up if the team
    # already exists.

    debug("creating teams in {org}".format(org=org.login))

    # dict of dst org teams keyed by name (str) with team object as value
    dst_teams = {}
    problems = []
    batch_repos = 50
    for name, repos in teams.items():
        pygithub.debug_ratelimit(g)
        debug("creating team {o}/'{t}'".format(
            o=org.login,
            t=name
        ))

        if dry_run:
            debug('  (noop)')
            continue

        dst_t = None
        try:
            if with_repos:
                debug("  with {n} member repos:".format(n=len(repos)))
                [debug("    {r}".format(r=r.full_name)) for r in repos]

                leftover_repos = repos[batch_repos:]
                if leftover_repos:
                    debug("  creating team with first {b} of {n} repos"
                          .format(
                              b=batch_repos,
                              n=len(repos)
                          ))
                dst_t = org.create_team(name, repo_names=repos[:batch_repos])
                if leftover_repos:
                    # add any repos over the batch limit individually to team
                    for r in leftover_repos:
                        debug("  adding repo {r}".format(r=r.full_name))
                        dst_t.add_to_repos(r)
            else:
                dst_t = org.create_team(name)
        except github.RateLimitExceededException:
            raise
        except github.GithubException as e:
            # if the error is for any cause other than the team already
            # existing, puke.
            team_exists = False
            if ignore_existing and 'errors' in e.data:
                for oops in e.data['errors']:
                    msg = oops['message']
                    if 'Name has already been taken' in msg:
                        # find existing team
                        dst_t = pygithub.get_teams_by_name(org, name)[0]
                        team_exists = True
            if not (ignore_existing and team_exists):
                msg = "error creating team: {t}".format(t=name)
                yikes = pygithub.CaughtOrganizationError(org, e, msg)
                if fail_fast:
                    raise yikes from None
                problems.append(yikes)
                error(yikes)
                break
        else:
            dst_teams[dst_t.name] = dst_t

    return dst_teams, problems
Пример #5
0
def run():
    args = parse_args()

    codetools.setup_logging(args.debug)

    global g
    g = pygithub.login_github(token_path=args.token_path, token=args.token)

    # protect destination org
    codetools.validate_org(args.dst_org)
    src_org = g.get_organization(args.src_org)
    dst_org = g.get_organization(args.dst_org)
    info("forking repos from: {org}".format(org=src_org.login))
    info("                to: {org}".format(org=dst_org.login))

    debug('looking for repos -- this can take a while for large orgs...')
    if args.team:
        debug('checking that selection team(s) exist')
        try:
            org_teams = list(src_org.get_teams())
        except github.RateLimitExceededException:
            raise
        except github.GithubException as e:
            msg = 'error getting teams'
            raise pygithub.CaughtOrganizationError(src_org, e, msg) from None

        missing_teams = [
            n for n in args.team if n not in [t.name for t in org_teams]
        ]
        if missing_teams:
            error("{n} team(s) do not exist:".format(n=len(missing_teams)))
            [error("  '{t}'".format(t=n)) for n in missing_teams]
            return
        fork_teams = [t for t in org_teams if t.name in args.team]
        repos = pygithub.get_repos_by_team(fork_teams)
        debug('selecting repos by membership in team(s):')
        [debug("  '{t}'".format(t=t.name)) for t in fork_teams]
    else:
        repos = pygithub.get_repos_by_team(fork_teams)

    src_repos = list(itertools.islice(repos, args.limit))

    repo_count = len(src_repos)
    if not repo_count:
        debug('nothing to do -- exiting')
        return

    debug("found {n} repos to be forked from org {src_org}:".format(
        n=repo_count, src_org=src_org.login))
    [debug("  {r}".format(r=r.full_name)) for r in src_repos]

    if args.copy_teams:
        debug('checking source repo team membership...')
        # dict of repo and team objects, keyed by repo name
        src_rt = find_teams_by_repo(src_repos)

        # extract a non-duplicated list of team names from all repos being
        # forked as a dict, keyed by team name
        src_teams = find_used_teams(src_rt)

        debug('found {n} teams in use within org {o}:'.format(n=len(src_teams),
                                                              o=src_org.login))
        [debug("  '{t}'".format(t=t)) for t in src_teams.keys()]

        # check for conflicting teams in dst org before attempting to create
        # any forks so its possible to bail out before any resources have been
        # created.
        debug('checking teams in destination org')
        conflicting_teams = pygithub.get_teams_by_name(dst_org,
                                                       list(src_teams.keys()))
        if conflicting_teams:
            raise TeamError(
                "found {n} conflicting teams in {o}: {teams}".format(
                    n=len(conflicting_teams),
                    o=dst_org.login,
                    teams=[t.name for t in conflicting_teams]))

    debug('there is no spoon...')
    problems = []
    pygithub.debug_ratelimit(g)
    dst_repos, skipped_repos, err = create_forks(dst_org,
                                                 src_repos,
                                                 fail_fast=args.fail_fast,
                                                 dry_run=args.dry_run)
    if err:
        problems += err

    if args.copy_teams:
        # filter out repos which were skipped
        # dict of str(fork_repo.name): fork_repo
        dst_forks = dict((r.name, r) for r in dst_repos)
        bad_repos = dict((r.name, r) for r in skipped_repos)
        # dict of str(team.name): [repos] to be created
        dst_teams = {}
        for name, repos in src_teams.items():
            dst_teams[name] = [
                dst_forks[r.name] for r in repos if r.name not in bad_repos
            ]

        _, err = create_teams(dst_org,
                              dst_teams,
                              with_repos=True,
                              fail_fast=args.fail_fast,
                              dry_run=args.dry_run)
        if err:
            problems += err

    if problems:
        msg = "{n} errors forking repo(s)/teams(s)".format(n=len(problems))
        raise codetools.DogpileError(problems, msg)
Пример #6
0
def create_teams(org,
                 teams,
                 with_repos=False,
                 ignore_existing=False,
                 fail_fast=False,
                 dry_run=False):
    assert isinstance(org, github.Organization.Organization), type(org)
    assert isinstance(teams, dict), type(teams)

    # it takes fewer api calls to create team(s) with an explicit list of
    # members after all repos have been forked but this blows up if the team
    # already exists.

    debug("creating teams in {org}".format(org=org.login))

    # dict of dst org teams keyed by name (str) with team object as value
    dst_teams = {}
    problems = []
    batch_repos = 50
    for name, repos in teams.items():
        pygithub.debug_ratelimit(g)
        debug("creating team {o}/'{t}'".format(o=org.login, t=name))

        if dry_run:
            debug('  (noop)')
            continue

        dst_t = None
        try:
            if with_repos:
                debug("  with {n} member repos:".format(n=len(repos)))
                [debug("    {r}".format(r=r.full_name)) for r in repos]

                leftover_repos = repos[batch_repos:]
                if leftover_repos:
                    debug("  creating team with first {b} of {n} repos".format(
                        b=batch_repos, n=len(repos)))
                dst_t = org.create_team(name, repo_names=repos[:batch_repos])
                if leftover_repos:
                    # add any repos over the batch limit individually to team
                    for r in leftover_repos:
                        debug("  adding repo {r}".format(r=r.full_name))
                        dst_t.add_to_repos(r)
            else:
                dst_t = org.create_team(name)
        except github.RateLimitExceededException:
            raise
        except github.GithubException as e:
            # if the error is for any cause other than the team already
            # existing, puke.
            team_exists = False
            if ignore_existing and 'errors' in e.data:
                for oops in e.data['errors']:
                    msg = oops['message']
                    if 'Name has already been taken' in msg:
                        # find existing team
                        dst_t = pygithub.get_teams_by_name(org, name)[0]
                        team_exists = True
            if not (ignore_existing and team_exists):
                msg = "error creating team: {t}".format(t=name)
                yikes = pygithub.CaughtOrganizationError(org, e, msg)
                if fail_fast:
                    raise yikes from None
                problems.append(yikes)
                error(yikes)
                break
        else:
            dst_teams[dst_t.name] = dst_t

    return dst_teams, problems