174 lines
5.7 KiB
Python
174 lines
5.7 KiB
Python
from __future__ import division, with_statement
|
|
|
|
from contextlib import closing
|
|
import json
|
|
import os
|
|
import sys
|
|
import time
|
|
import tarfile
|
|
from urllib.request import urlopen
|
|
import http.server
|
|
import socketserver
|
|
from threading import Thread
|
|
import subprocess
|
|
import webbrowser
|
|
|
|
|
|
PORT = 9841
|
|
if getattr(sys, 'frozen', False):
|
|
static_dir = os.path.dirname(sys.executable)
|
|
else:
|
|
static_dir = os.path.dirname(os.path.realpath(__file__))
|
|
static_dir = os.path.abspath(static_dir)
|
|
|
|
def makedirs(dirname):
|
|
if not os.path.exists(dirname):
|
|
os.makedirs(dirname)
|
|
|
|
def get_platform():
|
|
name = sys.platform
|
|
if name.startswith('darwin'):
|
|
name = 'darwin64'
|
|
elif name.startswith('linux'):
|
|
import platform
|
|
if platform.architecture()[0] == '64bit':
|
|
name = 'linux64'
|
|
else:
|
|
name = 'linux32'
|
|
return name
|
|
|
|
class Handler(http.server.SimpleHTTPRequestHandler):
|
|
def do_OPTIONS(self):
|
|
self.send_response(200, 'OK')
|
|
self.send_header('Allow', 'GET, POST, OPTIONS')
|
|
self.send_header('Access-Control-Allow-Origin', '*')
|
|
self.send_header('Access-Control-Allow-Headers', 'X-Requested-With')
|
|
self.send_header('Content-Length', '0')
|
|
self.end_headers()
|
|
|
|
def do_GET(self):
|
|
|
|
if self.path == '/status':
|
|
content = json.dumps(self.server.install.status).encode()
|
|
self.send_response(200, 'OK')
|
|
else:
|
|
path = os.path.join(static_dir, 'index.html' if self.path == '/' else self.path[1:])
|
|
if os.path.exists(path):
|
|
with open(path, 'rb') as fd:
|
|
content = fd.read()
|
|
self.send_response(200, 'OK')
|
|
content_type = {
|
|
'html': 'text/html',
|
|
'png': 'image/png',
|
|
'svg': 'image/svg+xml',
|
|
'txt': 'text/plain',
|
|
}.get(path.split('.')[-1], 'txt')
|
|
self.send_header('Content-Type', content_type)
|
|
else:
|
|
self.send_response(404, 'not found')
|
|
content = b'404 not found'
|
|
self.send_header('Access-Control-Allow-Origin', '*')
|
|
self.send_header('Content-Length', str(len(content)))
|
|
self.end_headers()
|
|
self.wfile.write(content)
|
|
|
|
def log_message(self, format, *args):
|
|
pass
|
|
|
|
class Install(Thread):
|
|
|
|
release_url = "http://downloads.openmedialibrary.com/release.json"
|
|
status = {
|
|
'step': 'Downloading...'
|
|
}
|
|
|
|
def __init__(self, target, httpd):
|
|
target = os.path.normpath(os.path.join(os.path.abspath(target)))
|
|
self.target = target
|
|
self.httpd = httpd
|
|
Thread.__init__(self)
|
|
self.daemon = True
|
|
self.start()
|
|
|
|
def run(self):
|
|
webbrowser.open('http://127.0.0.1:%s'%PORT)
|
|
target = self.target
|
|
makedirs(target)
|
|
os.chdir(target)
|
|
self.status["step"] = 'Downloading...'
|
|
release = self.get_release()
|
|
self.status["release"] = release
|
|
self.status["progress"] = 0
|
|
platform = get_platform()
|
|
if 'platform_win32' not in release['modules']:
|
|
release['modules']['platform_win32'] = {
|
|
'name': 'platform_win32-20160201-3-3d473b8.tar.bz2',
|
|
'version': '20160201-3-3d473b8.tar.bz2',
|
|
'platform': 'win32',
|
|
}
|
|
for module in sorted(release['modules']):
|
|
if release['modules'][module].get('platform', platform) == platform:
|
|
package_tar = release['modules'][module]['name']
|
|
url = self.release_url.replace('release.json', package_tar)
|
|
self.download(url, package_tar)
|
|
self.status["step"] = 'Installing...'
|
|
for module in sorted(release['modules']):
|
|
if release['modules'][module].get('platform', platform) == platform:
|
|
package_tar = release['modules'][module]['name']
|
|
tar = tarfile.open(package_tar)
|
|
tar.extractall()
|
|
tar.close()
|
|
os.unlink(package_tar)
|
|
makedirs('data')
|
|
with open('data/release.json', 'w') as fd:
|
|
json.dump(release, fd, indent=2)
|
|
self.status = {"relaunch": True}
|
|
open_oml(target)
|
|
time.sleep(5)
|
|
self.httpd.shutdown()
|
|
|
|
def download(self, url, filename):
|
|
dirname = os.path.dirname(filename)
|
|
if dirname:
|
|
makedirs(dirname)
|
|
with open(filename, 'wb') as f:
|
|
with closing(urlopen(url)) as u:
|
|
size = int(u.headers.get('content-length', 0))
|
|
self.status["size"] = size
|
|
available = 0
|
|
data = u.read(4096)
|
|
while data:
|
|
if size:
|
|
available += len(data)
|
|
f.write(data)
|
|
data = u.read(4096)
|
|
|
|
def get_release(self):
|
|
with closing(urlopen(self.release_url)) as u:
|
|
data = json.loads(u.read().decode())
|
|
return data
|
|
|
|
class Server(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
|
allow_reuse_address = True
|
|
|
|
class InstallServer(Thread):
|
|
def __init__(self, target):
|
|
self.target = target
|
|
Thread.__init__(self)
|
|
self.daemon = True
|
|
self.start()
|
|
|
|
def run(self):
|
|
httpd = Server(("127.0.0.1", PORT), Handler)
|
|
install = Install(self.target, httpd)
|
|
httpd.install = install
|
|
httpd.serve_forever()
|
|
|
|
def open_oml(base):
|
|
python = os.path.join(base, 'platform_win32', 'pythonw.exe')
|
|
pid = os.path.join(base, 'data', 'openmedialibrary.pid')
|
|
oml = os.path.join(base, 'openmedialibrary')
|
|
subprocess.Popen([python, 'oml', 'server', pid], cwd=oml, start_new_session=True)
|
|
|
|
def run(target):
|
|
return InstallServer(target)
|