|
1 | 1 | # Copyright The IETF Trust 2020, All Rights Reserved |
2 | 2 |
|
| 3 | + |
| 4 | +import github3 |
| 5 | + |
| 6 | +from collections import Counter |
| 7 | +from urllib.parse import urlparse |
| 8 | + |
| 9 | +from django.conf import settings |
3 | 10 | from django.core.management.base import BaseCommand |
4 | | -from django.db.models import F |
5 | 11 |
|
6 | 12 | from ietf.doc.models import DocExtResource |
7 | 13 | from ietf.group.models import GroupExtResource |
8 | 14 | from ietf.person.models import PersonExtResource |
9 | 15 |
|
| 16 | +# TODO: Think more about submodules. This currently will only take top level repos, with the assumption that the clone will include arguments to grab all the submodules. |
| 17 | +# As a consequence, we might end up pulling more than we need (or that the org or user expected) |
| 18 | +# Make sure this is what we want. |
| 19 | + |
10 | 20 | class Command(BaseCommand): |
11 | | - help = ('Locate information about gihub repositories to backup') |
| 21 | + help = ('Locate information about github repositories to backup') |
12 | 22 |
|
13 | 23 | def handle(self, *args, **options): |
14 | 24 |
|
15 | | - info_dict = {} |
16 | | - |
17 | | - |
18 | | - for repo in DocExtResource.objects.filter(name__slug='github_repo'): |
19 | | - if not repo.value.endswith('/'): |
20 | | - repo.value += '/' |
21 | | - if repo not in info_dict: |
22 | | - info_dict[repo.value] = [] |
23 | | - for username in DocExtResource.objects.filter(name__slug='github_username', doc=F('doc')): |
24 | | - info_dict[repo.value].push(username.value) |
25 | | - |
26 | | - for repo in GroupExtResource.objects.filter(name__slug='github_repo'): |
27 | | - if not repo.value.endswith('/'): |
28 | | - repo.value += '/' |
29 | | - if repo not in info_dict: |
30 | | - info_dict[repo.value] = [] |
31 | | - for username in GroupExtResource.objects.filter(name__slug='github_username', group=F('group')): |
32 | | - info_dict[repo.value].push(username.value) |
33 | | - |
34 | | - for repo in PersonExtResource.objects.filter(name__slug='github_repo'): |
35 | | - if not repo.value.endswith('/'): |
36 | | - repo.value += '/' |
37 | | - if repo not in info_dict: |
38 | | - info_dict[repo.value] = [] |
39 | | - for username in PersonExtResource.objects.filter(name__slug='github_username', person=F('person')): |
40 | | - info_dict[repo.value].push(username.value) |
41 | | - |
42 | | - #print (json.dumps(info_dict)) |
43 | | - # For now, all we need are the repo names |
44 | | - for name in info_dict.keys(): |
45 | | - print(name) |
| 25 | + if not settings.GITHUB_BACKUP_API_KEY: |
| 26 | + # TODO: complain |
| 27 | + return |
| 28 | + |
| 29 | + github = github3.login(token = settings.GITHUB_BACKUP_API_KEY) |
| 30 | + owners = dict() |
| 31 | + repos = set() |
| 32 | + |
| 33 | + for cls in (DocExtResource, GroupExtResource, PersonExtResource): |
| 34 | + for res in cls.objects.filter(name_id__in=('github_repo','github_org')): |
| 35 | + path_parts = urlparse(res.value).path.strip('/').split('/') |
| 36 | + if not path_parts or not path_parts[0]: |
| 37 | + continue |
| 38 | + |
| 39 | + owner = path_parts[0] |
| 40 | + |
| 41 | + if owner not in owners: |
| 42 | + try: |
| 43 | + gh_owner = github.user(username=owner) |
| 44 | + owners[owner] = gh_owner |
| 45 | + except github3.exceptions.NotFoundError: |
| 46 | + continue |
| 47 | + |
| 48 | + if gh_owner.type in ('User', 'Organization'): |
| 49 | + if len(path_parts) > 1: |
| 50 | + repo = path_parts[1] |
| 51 | + if (owner, repo) not in repos: |
| 52 | + try: |
| 53 | + _ = github.repository(owner,repo) |
| 54 | + repos.add( (owner, repo) ) |
| 55 | + except github3.exceptions.NotFoundError: |
| 56 | + continue |
| 57 | + else: |
| 58 | + for repo in github.repositories_by(owner): |
| 59 | + repos.add( (owner, repo.name) ) |
| 60 | + |
| 61 | + owner_types = Counter([owners[owner].type for owner in owners]) |
| 62 | + print ("Owners:") |
| 63 | + for key in owner_types: |
| 64 | + print(" ",key,':',owner_types[key]) |
| 65 | + print ("Repositories:", len(repos)) |
| 66 | + for repo in sorted(repos): |
| 67 | + print(" https://github.com/%s/%s" % repo ) |
0 commit comments