-
Notifications
You must be signed in to change notification settings - Fork 5
/
github.py
107 lines (86 loc) · 3.41 KB
/
github.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import base64
import click
import git
import logging
import tempfile
import os
from .local import Index as LocalIndex
from ..helpers.click import click_additional_options
log = logging.getLogger(__name__)
_github_private_key = None
_github_url = None
class Index(LocalIndex):
def __init__(self):
super().__init__()
# We need to write the private key to disk: GitPython can only use
# SSH-keys that are written on disk.
if _github_private_key:
self._github_private_key_file = tempfile.NamedTemporaryFile()
self._github_private_key_file.write(_github_private_key)
self._github_private_key_file.flush()
self._ssh_command = f"ssh -i {self._github_private_key_file.name}"
else:
self._ssh_command = None
try:
self._git = git.Repo(self._folder)
except git.exc.NoSuchPathError:
self._git = git.Repo.init(self._folder)
except git.exc.InvalidGitRepositoryError:
self._git = git.Repo.init(self._folder)
# Make sure the origin is set correctly
if "origin" not in self._git.remotes:
self._git.create_remote("origin", _github_url)
origin = self._git.remotes.origin
if origin.url != _github_url:
origin.set_url(_github_url)
def _remove_empty_folders(self, parent_folder):
removed = False
for root, folders, files in os.walk(parent_folder, topdown=False):
if root.startswith(".git"):
continue
if not folders and not files:
os.rmdir(root)
removed = True
return removed
def _fetch_latest(self):
log.info("Updating index to latest version from GitHub")
origin = self._git.remotes.origin
# Checkout the latest master, removing and commits/file changes local
# might have.
with self._git.git.custom_environment(GIT_SSH_COMMAND=self._ssh_command):
try:
origin.fetch()
except git.exc.BadName:
# When the garbage collector kicks in, GitPython gets confused and
# throws a BadName. The best solution? Just run it again.
origin.fetch()
origin.refs.master.checkout(force=True, B="master")
for file_name in self._git.untracked_files:
os.unlink(f"{self._folder}/{file_name}")
# We might end up with empty folders, which the rest of the
# application doesn't really like. So remove them. Keep repeating the
# function until no folders are removed anymore.
while self._remove_empty_folders(self._folder):
pass
def reload(self, application):
self._fetch_latest()
return super().reload(application)
@click_additional_options
@click.option(
"--index-github-url",
help="Repository URL on GitHub. (index=github only)",
default="https://github.com/OpenTTD/BaNaNaS",
show_default=True,
metavar="URL",
)
@click.option(
"--index-github-private-key",
help="Base64-encoded private key to access GitHub."
"Always use this via an environment variable!"
"(index=github only)",
)
def click_index_github(index_github_url, index_github_private_key):
global _github_url, _github_private_key
_github_url = index_github_url
if index_github_private_key:
_github_private_key = base64.b64decode(index_github_private_key)