Skip to content

Commit f4fd4b1

Browse files
committed
Gather actual repos to backup takinging user and organizational owners into account, iterating through owner repos when necessary using the github api.
- Legacy-Id: 18384
1 parent 2af4246 commit f4fd4b1

2 files changed

Lines changed: 56 additions & 33 deletions

File tree

Lines changed: 55 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,67 @@
11
# Copyright The IETF Trust 2020, All Rights Reserved
22

3+
4+
import github3
5+
6+
from collections import Counter
7+
from urllib.parse import urlparse
8+
9+
from django.conf import settings
310
from django.core.management.base import BaseCommand
4-
from django.db.models import F
511

612
from ietf.doc.models import DocExtResource
713
from ietf.group.models import GroupExtResource
814
from ietf.person.models import PersonExtResource
915

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+
1020
class Command(BaseCommand):
11-
help = ('Locate information about gihub repositories to backup')
21+
help = ('Locate information about github repositories to backup')
1222

1323
def handle(self, *args, **options):
1424

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 )

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ django-widget-tweaks>=1.4.2
2727
docutils>=0.12,!=0.15
2828
factory-boy>=2.9.0,<3
2929
Faker>=0.8.8,!=0.8.9,!=0.8.10 # from factory-boy # Faker 0.8.9,0.8.10 sometimes return string names instead of unicode.
30+
github3.py>=1.2
3031
hashids>=1.1.0
3132
html2text>=2019.8.11
3233
html5lib>=1.0.1

0 commit comments

Comments
 (0)