336 lines
10 KiB
Python
336 lines
10 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
|
|
from os.path import join, exists, dirname
|
|
import os
|
|
import shutil
|
|
import signal
|
|
import subprocess
|
|
import sys
|
|
|
|
import settings
|
|
from utils import run, get
|
|
|
|
root_dir = dirname(settings.base_dir)
|
|
|
|
HIDDEN = ['install_update', 'install_launcher', 'uninstall_launcher']
|
|
|
|
def r(*cmd):
|
|
return subprocess.call(cmd)
|
|
|
|
def version(module):
|
|
if os.path.exists(join(root_dir, module, '.git')):
|
|
os.chdir(join(root_dir, module))
|
|
version = get('git', 'log', '-1', '--format=%cd', '--date=iso').split(' ')[0].replace('-', '')
|
|
version += '-' + get('git', 'rev-list', 'HEAD', '--count').strip()
|
|
version += '-' + get('git', 'describe', '--always').strip()
|
|
os.chdir(root_dir)
|
|
else:
|
|
if 'modules' in settings.release and module in settings.release['modules']:
|
|
version = settings.release['modules'][module]['version']
|
|
else:
|
|
version = -1
|
|
return version
|
|
|
|
def command_version(*args):
|
|
"""
|
|
Print current version
|
|
"""
|
|
print(version('openmedialibrary'))
|
|
|
|
def command_debug(*args):
|
|
"""
|
|
Start in debug mode
|
|
"""
|
|
pass
|
|
|
|
def command_start(*args):
|
|
"""
|
|
Start Open Media Libary
|
|
"""
|
|
pass
|
|
|
|
def command_stop(*args):
|
|
"""
|
|
Stop Open Media Libary
|
|
"""
|
|
if sys.platform == 'win32':
|
|
from utils import check_pid
|
|
if args:
|
|
pid = args[0]
|
|
else:
|
|
pid = os.path.join(settings.data_path, 'openmedialibrary.pid')
|
|
try:
|
|
with open(pid) as fd:
|
|
pid = int(fd.read())
|
|
except:
|
|
return
|
|
if check_pid(pid):
|
|
os.kill(pid, signal.SIGTERM)
|
|
|
|
def command_restart(*args):
|
|
"""
|
|
Restart Open Media Libary
|
|
"""
|
|
if sys.platform == 'win32':
|
|
from urllib.request import urlopen
|
|
from urllib.parse import urlencode
|
|
url = 'http://{address}:{port}/api/'.format(**settings.server)
|
|
data = urlencode({'action': 'quit', 'data': '{}'}).encode()
|
|
try:
|
|
urlopen(url, data, timeout=2)
|
|
except:
|
|
pass
|
|
from utils import check_pid, ctl
|
|
pidfile = os.path.join(settings.data_path, 'openmedialibrary.pid')
|
|
try:
|
|
with open(pidfile) as fd:
|
|
pid = int(fd.read())
|
|
except:
|
|
pid = None
|
|
if pid and check_pid(pid):
|
|
os.kill(pid, signal.SIGTERM)
|
|
ctl('server', pidfile)
|
|
|
|
def command_install_launcher(*args):
|
|
"""
|
|
Install launcher
|
|
"""
|
|
import integration
|
|
integration.install_launcher()
|
|
|
|
def command_uninstall_launcher(*args):
|
|
"""
|
|
Uninstall launcher
|
|
"""
|
|
import integration
|
|
integration.uninstall_launcher()
|
|
|
|
def command_install_update(*args):
|
|
"""
|
|
Install available updates
|
|
"""
|
|
pass
|
|
|
|
def command_update(*args):
|
|
"""
|
|
Update to latest development version
|
|
"""
|
|
import update
|
|
print('Downloading...')
|
|
if not update.download():
|
|
print('Download failed')
|
|
return
|
|
print('Installing...')
|
|
if not update.install():
|
|
print("Installation failed")
|
|
|
|
def command_postupdate(*args):
|
|
"""
|
|
Called after update with -o old -n new
|
|
"""
|
|
o, old, n, new = args
|
|
if o != '-o' or n != '-n':
|
|
print('usage: -o oldversion -n newversion')
|
|
sys.exit(1)
|
|
if old <= '20140521-65-e14c686' and new > '20140521-65-e14c686':
|
|
if not os.path.exists(settings.db_path) and sys.platform != 'win32':
|
|
r('./ctl', 'setup')
|
|
import setup
|
|
setup.upgrade_db(old, new)
|
|
|
|
def command_setup(*args):
|
|
"""
|
|
Setup new node
|
|
"""
|
|
import setup
|
|
setup.create_db()
|
|
|
|
def command_update_static(*args):
|
|
"""
|
|
Update static files
|
|
"""
|
|
import setup
|
|
import utils
|
|
setup.create_db()
|
|
old_oxjs = os.path.join(settings.static_path, 'oxjs')
|
|
oxjs = os.path.join(settings.top_dir, 'oxjs')
|
|
if os.path.exists(old_oxjs) and not os.path.exists(oxjs):
|
|
shutil.move(old_oxjs, oxjs)
|
|
if not os.path.exists(oxjs):
|
|
r('git', 'clone', '--depth', '1', 'https://code.0x2620.org/0x2620/oxjs.git', oxjs)
|
|
elif os.path.exists(os.path.join(oxjs, '.git')):
|
|
os.system('cd "%s" && git pull' % oxjs)
|
|
r('python3', os.path.join(oxjs, 'tools', 'build', 'build.py'), '-nogeo')
|
|
utils.update_static()
|
|
reader = os.path.join(settings.top_dir, 'reader')
|
|
if not os.path.exists(reader):
|
|
r('git', 'clone', '--depth', '1', 'https://code.0x2620.org/0x2620/openmedialibrary_reader.git', reader)
|
|
elif os.path.exists(os.path.join(reader, '.git')):
|
|
os.system('cd "%s" && git pull' % reader)
|
|
|
|
def command_release(*args):
|
|
"""
|
|
Release new version
|
|
"""
|
|
print('checking...')
|
|
import base64
|
|
import ed25519
|
|
import hashlib
|
|
import json
|
|
import OpenSSL.crypto
|
|
from OpenSSL.crypto import load_privatekey, FILETYPE_PEM
|
|
import os
|
|
|
|
release_name = args[0] if args else 'release'
|
|
|
|
os.chdir(root_dir)
|
|
with open(os.path.expanduser('~/.openmedialibrary_release.key'), 'rb') as fd:
|
|
SIG_KEY=ed25519.SigningKey(fd.read())
|
|
SIG_ENCODING='base64'
|
|
with open(os.path.expanduser('~/.openmedialibrary_tls_release.key'), 'rb') as fd:
|
|
tls_key = load_privatekey(FILETYPE_PEM, fd.read())
|
|
|
|
def sign(release):
|
|
value = []
|
|
for module in sorted(release['modules']):
|
|
value += ['%s/%s' % (release['modules'][module]['version'], release['modules'][module]['sha1'])]
|
|
value = '\n'.join(value).encode()
|
|
sig = SIG_KEY.sign(value, encoding=SIG_ENCODING).decode()
|
|
release['signature'] = sig
|
|
digest = 'sha1'
|
|
tls_sig = OpenSSL.crypto.sign(tls_key, value, digest)
|
|
release['signature_%s'%digest] = base64.b64encode(tls_sig).decode()
|
|
import update
|
|
if not update.verify(release):
|
|
print('verifiying signature failed!')
|
|
return False
|
|
return True
|
|
|
|
def sha1sum(path):
|
|
h = hashlib.sha1()
|
|
with open(path, 'rb') as fd:
|
|
for chunk in iter(lambda: fd.read(128*h.block_size), b''):
|
|
h.update(chunk)
|
|
return h.hexdigest()
|
|
|
|
MODULES = ['platform', 'openmedialibrary', 'oxjs', 'reader']
|
|
PLATFORM_MODULES = {
|
|
'platform_linux32': 'linux32',
|
|
'platform_linux64': 'linux64',
|
|
'platform_linux_armv7l': 'linux_armv7l',
|
|
'platform_linux_aarch64': 'linux_aarch64',
|
|
'platform_darwin64': 'darwin64',
|
|
'platform_win32': 'win32',
|
|
}
|
|
MODULES += list(PLATFORM_MODULES)
|
|
VERSIONS = {module:version(module) for module in MODULES}
|
|
|
|
EXCLUDE = [
|
|
'--exclude', '.git', '--exclude', '.bzr',
|
|
'--exclude', 'pip_cache',
|
|
'--exclude', '.*.swp', '--exclude', '._*', '--exclude', '.DS_Store',
|
|
'--exclude', 'Geo/png'
|
|
]
|
|
|
|
#run('./ctl', 'update_static')
|
|
for module in MODULES:
|
|
tar = join('updates', '%s-%s.tar.bz2' % (module, VERSIONS[module]))
|
|
if not exists(tar):
|
|
cmd = ['tar', 'cvjf', tar] + EXCLUDE
|
|
if module in ('openmedialibrary', ):
|
|
cmd += ['--exclude', '*.pyc']
|
|
if module == 'openmedialibrary':
|
|
cmd += ['--exclude', 'gunicorn.pid']
|
|
if module == 'oxjs':
|
|
cmd += ['--exclude', 'oxjs/examples']
|
|
if module == 'platform_win32':
|
|
cmd += ['--exclude', 'build', '--exclude', 'dist']
|
|
cmd += [module + '/']
|
|
run(*cmd)
|
|
release = {}
|
|
release['modules'] = {module: {
|
|
'name': '%s-%s.tar.bz2' % (module, VERSIONS[module]),
|
|
'version': VERSIONS[module],
|
|
'sha1': sha1sum(join('updates', '%s-%s.tar.bz2' % (module, VERSIONS[module])))
|
|
} for module in MODULES}
|
|
for module in PLATFORM_MODULES:
|
|
release['modules'][module]['platform'] = PLATFORM_MODULES[module]
|
|
if sign(release):
|
|
with open('updates/%s.json' % release_name, 'w') as fd:
|
|
json.dump(release, fd, indent=2, sort_keys=True)
|
|
print('signed latest release in updates/%s.json' % release_name)
|
|
|
|
def command_shell(*args):
|
|
'''
|
|
Runs a Python shell inside the application context.
|
|
'''
|
|
context = None
|
|
banner = 'Open Media Library'
|
|
|
|
import db
|
|
with db.session():
|
|
# Try BPython
|
|
try:
|
|
from bpython import embed
|
|
embed(banner=banner, locals_=context)
|
|
return
|
|
except ImportError:
|
|
pass
|
|
|
|
# Try IPython
|
|
try:
|
|
try:
|
|
# 0.10.x
|
|
from IPython.Shell import IPShellEmbed
|
|
ipshell = IPShellEmbed(banner=banner)
|
|
ipshell(global_ns=dict(), local_ns=context)
|
|
except ImportError:
|
|
# 0.12+
|
|
from IPython.terminal.ipapp import TerminalIPythonApp
|
|
app = TerminalIPythonApp.instance()
|
|
app.extensions = ['autoreload']
|
|
app.exec_lines = ['%autoreload 2']
|
|
app.display_banner = False
|
|
print(banner)
|
|
app.initialize(argv=[])
|
|
app.start()
|
|
return
|
|
except ImportError:
|
|
pass
|
|
|
|
import code
|
|
# Use basic python shell
|
|
code.interact(banner, local=context)
|
|
|
|
def command_dump_json(*args):
|
|
"""
|
|
Dump items to json
|
|
"""
|
|
if not args:
|
|
print('usage: ./ctl json_dump dump.json')
|
|
sys.exit(1)
|
|
import db
|
|
import state
|
|
with db.session():
|
|
library = state.user().library
|
|
library.export_json(args[0])
|
|
|
|
def main():
|
|
actions = globals()
|
|
commands = [c[8:] for c in actions if c.startswith('command_')]
|
|
command = sys.argv[1] if len(sys.argv) > 1 else None
|
|
if command and command in commands:
|
|
globals()["command_%s"%command](*sys.argv[2:])
|
|
else:
|
|
print("usage: ./ctl [action]")
|
|
indent = max([len(command) for command in commands]) + 4
|
|
for command in sorted(commands):
|
|
if command in HIDDEN:
|
|
continue
|
|
space = ' ' * (indent - len(command))
|
|
info = actions["command_%s"%command].__doc__.split('\n')
|
|
info = [' %s%s' % (' ' * indent, i.strip()) for i in info]
|
|
info = '\n'.join(info).strip()
|
|
print((" %s%s%s" % (command, space, info)))
|
|
sys.exit(1)
|