diff --git a/ctl b/ctl index 44df4ba..54dcbbd 100755 --- a/ctl +++ b/ctl @@ -87,20 +87,24 @@ if [ "$1" == "ui" ]; then exit $? fi if [ "$1" == "update" ]; then - cd "$BASE/$NAME" - OLD=`"$0" version` - cd "$BASE/platform" - echo Update platform.. - git pull - echo Update $NAME.. - cd "$BASE/$NAME" - git pull - find . -name '*.pyc' -exec rm "{}" \; - $0 setup - $0 update_static > /dev/null - NEW=`"$0" version` - $0 postupdate -o $OLD -n $NEW - exit + if [ -e $BASE/$NAME/.git ]; then + cd "$BASE/$NAME" + OLD=`"$0" version` + cd "$BASE/platform" + echo Update platform.. + git pull + echo Update $NAME.. + cd "$BASE/$NAME" + git pull + find . -name '*.pyc' -exec rm "{}" \; + $0 setup + $0 update_static > /dev/null + NEW=`"$0" version` + $0 postupdate -o $OLD -n $NEW + exit + else + python2 oml update + fi fi if [ "$1" == "python" ]; then cd "$BASE/$NAME" diff --git a/oml/commands.py b/oml/commands.py index 795e480..fa46f4e 100644 --- a/oml/commands.py +++ b/oml/commands.py @@ -27,14 +27,16 @@ def r(*cmd): return subprocess.call(cmd) def version(module): - 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) + 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: + version = settings.release['modules'][module]['version'] return version - class Version(Command): """ Print current version @@ -68,7 +70,11 @@ class Update(Command): Update to latest development version """ def run(self): - pass + import update + if update.update(): + print "OK" + else: + print "FAILED" class PostUpdate(Command): """ diff --git a/oml/settings.py b/oml/settings.py index 9fddf29..1f332c7 100644 --- a/oml/settings.py +++ b/oml/settings.py @@ -10,7 +10,7 @@ from pdict import pdict base_dir = os.path.normpath(os.path.join(os.path.abspath(os.path.dirname(__file__)), '..')) static_path = os.path.join(base_dir, 'static') -updates_path = os.path.join(base_dir, 'updates') +updates_path = os.path.normpath(os.path.join(base_dir, '..', 'updates')) oml_config_path = os.path.join(base_dir, 'config.json') @@ -65,6 +65,7 @@ else: os.chmod(key_path, 0400) USER_ID = vk.to_ascii(encoding='base64') +OML_UPDATE_KEY='K55EZpPYbP3X+3mA66cztlw1sSaUMqGwfTDKQyP2qOU' if 'modules' in release and 'openmedialibrary' in release['modules']: MINOR_VERSION = release['modules']['openmedialibrary']['version'] diff --git a/oml/update.py b/oml/update.py new file mode 100644 index 0000000..9f58628 --- /dev/null +++ b/oml/update.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# vi:si:et:sw=4:sts=4:ts=4 +from __future__ import division, with_statement + +from contextlib import closing +import json +import os +import tarfile +import urllib2 +import shutil +import subprocess + +import requests +import ed25519 +import ox + +import settings + +ENCODING='base64' +RELEASE_URL = "http://downloads.openmedialibrary.com/release.json" + +def verify(release): + vk = ed25519.VerifyingKey(settings.OML_UPDATE_KEY, encoding=ENCODING) + value = [] + for module in sorted(release['modules']): + value += [str('%s/%s' % (release['modules'][module]['version'], release['modules'][module]['sha1']))] + value = '\n'.join(value) + sig = str(release['signature']) + try: + vk.verify(sig, value, encoding=ENCODING) + except ed25519.BadSignatureError: + return False + return True + +def download(self, url, filename): + dirname = os.path.dirname(filename) + if dirname and not os.path.exists(dirname): + os.makedirs(dirname) + with open(filename, 'w') as f: + with closing(urllib2.urlopen(url)) as u: + data = u.read(4096) + while data: + f.write(data) + data = u.read(4096) + +def new_version(): + if settings.release: + r = requests.get(RELEASE_URL) + release_data = r.content + release = json.loads(release_data) + old = settings.release['modules']['openmedialibrary']['version'] + new = release['modules']['openmedialibrary']['version'] + return verify(release) and old < new + +def update(): + r = requests.get(RELEASE_URL) + release_data = r.content + release = json.loads(release_data) + old = settings.release['modules']['openmedialibrary']['version'] + new = release['modules']['openmedialibrary']['version'] + if verify(release) and old < new: + with open(os.path.join(settings.updates_path, 'release.json'), 'w') as fd: + fd.write(release_data) + os.chdir(settings.base_dir) + for module in release['modules']: + package_tar = os.path.join(settings.updates_path, release['modules'][module]['name']) + url = RELEASE_URL.replace('release.json', package_tar) + download(url, package_tar) + if ox.sha1sum(package_tar) == release['modules'][module]['sha1']: + shutil.move(module, '%s_old' % module) + tar = tarfile.open(package_tar) + tar.extractall() + tar.close() + shutil.rmtree('%s_old' % module) + else: + return False + os.unlink(package_tar) + with open(os.path.join(settings.config_dir, 'release.json'), 'w') as fd: + fd.write(release_data) + cmd = ['./ctl', 'stop'] + subprocess.call(cmd) + cmd = ['./ctl', 'setup'] + subprocess.call(cmd) + cmd = ['./ctl', 'postupdate', '-o', old, '-n', new] + subprocess.call(cmd) + cmd = ['./ctl', 'start'] + return True + return True