forked from letsRobot/letsrobot
-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathupdate.py
132 lines (113 loc) · 3.92 KB
/
update.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import subprocess
import logging
import sys
import re
import robot_util
import extended_command
log = logging.getLogger('RemoTV.update')
update_available = False
def checkForUpdates():
global update_available
isOod = subprocess.check_output('git fetch && git status -b -uno', shell=True)
isOod = str(isOod)
if "behind" in isOod:
update_available = re.search(r'\d+(\scommits|\scommit)', isOod).group(0).split()[0]
return True
else:
return False
def checkLocalChanges():
untracked = 0
modified = 0
try:
output = subprocess.check_output(["git", "status", "--porcelain"])
except subprocess.CalledProcessError as error:
log.error(error)
return False
for item in output.splitlines():
item = item.split()
if item[0] == b'M':
modified = modified + 1
elif item[0] == b'??':
untracked = untracked + 1
log.info("{} modified, {} untracked files".format(modified, untracked))
if modified != 0:
log.error("Error: Modified core files detected!")
return False
else:
return True
def doUpdate():
# get the old head so we can revert if something goes wrong.
try:
old_head = subprocess.check_output(["git", "rev-parse", "HEAD"]).rstrip()
except subprocess.CalledProcessError as error:
log.error(error)
return False
# run the update
try:
subprocess.check_output(["git", "pull"])
except subprocess.CalledProcessError as error:
log.error(error)
# attempt to revert to old head
subprocess.call(["git", "reset","--hard" ,old_head])
return False
# test the updated controller.
try:
subprocess.check_output([sys.executable, "controller.py", "--test"])
except subprocess.CalledProcessError as error:
log.error(error)
# attempt to revert to old head
subprocess.call(["git", "reset", "--hard", old_head])
return False
return True
def update_handler(command, args):
global update_available
if extended_command.is_authed(args['sender']) == 2:
if len(command) == 1: # just .update
if not update_available:
if checkForUpdates():
robot_util.sendChatMessage(
"{} updates available. Send '.update yes' to apply updates.".format(update_available))
else:
robot_util.sendChatMessage(
"Robot is already up to date. Nothing to do!")
else:
robot_util.sendChatMessage(
"{} updates available. Send '.update yes' to apply updates.".format(update_available))
else:
if command[1] == "yes":
if checkLocalChanges():
if doUpdate():
update_fetched = False
robot_util.sendChatMessage(
'Update completed. Restart for changes to take effect.')
else:
robot_util.sendChatMessage(
'Update Failed. run "git pull" locally to determine error.')
else:
robot_util.sendChatMessage(
'Automatic Update aborted, you have modified core files.')
def setup(config):
extended_command.add_command('.update', update_handler)
if __name__ == "__main__":
def sendChatDummy(*args):
return True
robot_util.sendChatMessage = sendChatDummy
if checkForUpdates():
print("Updates Available.")
if (sys.version_info > (3, 0)):
key = input('Apply updates (y/n)? ').rstrip()
else:
key = raw_input('Apply updates (y/n)? ').rstrip()
key = str(key.lower())
if key == "y":
if checkLocalChanges():
if doUpdate():
print("Update completed successfully")
else:
print("Update failed, attempted revert")
else:
print("Local changes detected, update aborted")
else:
print("Exited without updating")
else:
print("Already up to date")