This repository has been archived by the owner on Aug 9, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathupdater.py
159 lines (118 loc) · 4.68 KB
/
updater.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# Required for sending a GET request for update checks
from multiprocessing import Process, Manager, freeze_support
import requests
import os
import traceback
import ssl
# Required for downloading a new version automatically
from tqdmLite import tqdm
import zipfile
# import traceback
import subprocess
from py2exeUtils import scriptDir as SCRIPT_PATH
import py2exeUtils as p2eU
ZIP_DOWNLOAD_PATH = SCRIPT_PATH+'.updateSnL/'
req_error = requests.exceptions
# =============================================================================
# FUNCTIONS THAT USE GITHUB API TO RETRIEVE NEWEST RELEASE
# =============================================================================
def f(d):
try:
d['value'] = d['a']('https://api.github.com/repos/Son-Guhun/SaveNLoad/releases/latest',
verify=d['b']+'cacert.pem')
except KeyboardInterrupt:
pass
def getNewestVersionEx():
"""
Sends a GET request to GitHub to retrieve the latest release.
Returns a dict containing the the json-encoded content of the response.
"""
if __name__ == '__main__':
freeze_support()
manager = Manager()
# Create manager dict to send data to our child process
d = manager.dict()
d['a'] = requests.get
d['b'] = SCRIPT_PATH
p = Process(target=f, args=(d, ))
p.start()
i = 0
while p.is_alive() and i < 334: # 0.03 * 334 ~= 10 seconds
p.join(0.03) # Allow user to press ctrl+C
i += 1
if p.is_alive():
p.terminate()
raise req_error.ConnectionError('Connection did not complete within timeout.')
try:
return d['value'].json()
except:
print
traceback.print_exc()
print "\n\nError when attemtping to update. Continuing to main routine."
return None
def getNewestVersion():
"""
Sends a request to GitHub to retrieve the latest release.
Returns a string containing the tag_name of the latest release.
Eg: v2.2
Uses getNewVersionEx()
"""
a = getNewestVersionEx()
return a['tag_name'] if a else ''
# =============================================================================
# FILE IO AND AUTOUPDATE
# =============================================================================
def makeDirSafe(*args, **kargs):
"""
Make a directory. Does not raise an error if the directory already exists.
"""
try:
os.mkdir(*args, **kargs)
except WindowsError as error:
if error.winerror == 183:
pass # Windows error: cannot create an existing file
else:
raise error
def extractUpdate(zip_path, destination_folder, delete=False):
"""
Extracts the contents of a .zip file into a given destination_folder.
Uses makeDirSafe to ensure the folder exists.
If they keyword argument delete is set to true, the zip file is deleted
after its contents have been fully extracted.
"""
with zipfile.ZipFile(zip_path, 'r') as zip_:
makeDirSafe(destination_folder)
zip_.extractall(destination_folder)
if delete:
os.remove(zip_path)
def downloadNewestVersion(download_folder, zip_name='Update.zip'):
"""
Uses getNewestVersionEx() to get a download link to the latest release.
Downloads the latest release while displaying a progress bar.
Returns the path to the created zip file.
"""
# Get download link
release_dict = getNewestVersionEx()
download_link = release_dict['assets'][0]['browser_download_url']
makeDirSafe(download_folder)
# Make GET request to download link, determine file size and .zip file path
response = requests.get(download_link, verify=SCRIPT_PATH+'cacert.pem', stream=True)
file_size = int(response.headers['Content-Length'])
zip_path = download_folder + zip_name
# Download file as a stream, use tqdm to create a progress bar
with open(zip_path, "wb") as handle:
for data in tqdm(response.iter_content(chunk_size=1024*500),
unit='kb', unit_scale=500, total=file_size/1024./500.):
handle.write(data)
return zip_path
def autoUpdate():
DETACHED_PROCESS = 0x00000008
if not p2eU.frozen:
print 'Auto Update is only supported when using the compiled executable.'
return False
zip_path = downloadNewestVersion(ZIP_DOWNLOAD_PATH)
extractUpdate(zip_path, ZIP_DOWNLOAD_PATH, delete=True)
subprocess.Popen([SCRIPT_PATH+'.updateSnL/SaveNLoad/autoupdate.exe', 'copyFiles', SCRIPT_PATH],
stdout=subprocess.PIPE, stdin=subprocess.PIPE,
creationflags=DETACHED_PROCESS)
exit()