diff options
Diffstat (limited to 'morphlib/yapp.py')
-rw-r--r-- | morphlib/yapp.py | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/morphlib/yapp.py b/morphlib/yapp.py new file mode 100644 index 00000000..c0e41fdb --- /dev/null +++ b/morphlib/yapp.py @@ -0,0 +1,120 @@ +# Copyright (C) 2014 Codethink Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# =*= License: GPL-2 =*= + +import contextlib +import os +import datetime +import shutil +from subprocess import check_output +from subprocess import call +from multiprocessing import cpu_count +settings = {} + + +def log(component, message='', data=''): + ''' Print a timestamped log. ''' + name = component + try: + name = component['name'] + except Exception, e: + pass + + timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + log_entry = '%s [%s] %s %s\n' % (timestamp, name, message, data) + print(log_entry), + + +def run_cmd(this, command): + log(this, 'Running command\n\n', command) + with open(settings['logfile'], "a") as logfile: + if call(['sh', '-c', command], stdout=logfile, stderr=logfile): + log(this, 'ERROR: in directory %s command failed:' % os.getcwd(), + command) + raise SystemExit + + +@contextlib.contextmanager +def setup(target, arch): + try: + settings['arch'] = arch + settings['no-ccache'] = True + settings['cache-server-url'] = \ + 'http://git.baserock.org:8080/1.0/sha1s?' + settings['base'] = os.path.expanduser('~/.ybd/') + if os.path.exists('/src'): + settings['base'] = '/src' + settings['caches'] = os.path.join(settings['base'], 'cache') + settings['artifacts'] = os.path.join(settings['caches'], + 'ybd-artifacts') + settings['gits'] = os.path.join(settings['caches'], 'gits') + settings['staging'] = os.path.join(settings['base'], 'staging') + timestamp = datetime.datetime.now().strftime('%Y%m%d-%H%M%S') + settings['assembly'] = os.path.join(settings['staging'], + target + '-' + timestamp) + settings['max_jobs'] = max(int(cpu_count() * 1.5 + 0.5), 1) + + for directory in ['base', 'caches', 'artifacts', 'gits', + 'staging', 'assembly']: + if not os.path.exists(settings[directory]): + os.mkdir(settings[directory]) + + # git replace means we can't trust that just the sha1 of a branch + # is enough to say what it contains, so we turn it off by setting + # the right flag in an environment variable. + os.environ['GIT_NO_REPLACE_OBJECTS'] = '1' + + + yield + + finally: + # assuming success, we can remove the 'assembly' directory + # shutil.rmtree(settings['assembly']) + log(target, 'Assembly directory is still at', settings['assembly']) + + +@contextlib.contextmanager +def chdir(dirname=None, env={}): + currentdir = os.getcwd() + currentenv = {} + try: + if dirname is not None: + os.chdir(dirname) + for key, value in env.items(): + currentenv[key] = os.environ.get(key) + os.environ[key] = value + yield + finally: + for key, value in currentenv.items(): + if value: + os.environ[key] = value + else: + del os.environ[key] + os.chdir(currentdir) + + +@contextlib.contextmanager +def timer(this, start_message=''): + starttime = datetime.datetime.now() + log(this, start_message) + try: + yield + finally: + td = datetime.datetime.now() - starttime + hours, remainder = divmod(int(td.total_seconds()), 60*60) + minutes, seconds = divmod(remainder, 60) + td_string = "%02d:%02d:%02d" % (hours, minutes, seconds) + log(this, 'Elapsed time', td_string) |