summaryrefslogtreecommitdiffstats
path: root/build_tools/larch7/larch0/cli/backend.py
diff options
context:
space:
mode:
Diffstat (limited to 'build_tools/larch7/larch0/cli/backend.py')
-rw-r--r--build_tools/larch7/larch0/cli/backend.py444
1 files changed, 0 insertions, 444 deletions
diff --git a/build_tools/larch7/larch0/cli/backend.py b/build_tools/larch7/larch0/cli/backend.py
deleted file mode 100644
index 95b01bd..0000000
--- a/build_tools/larch7/larch0/cli/backend.py
+++ /dev/null
@@ -1,444 +0,0 @@
-# backend.py - for the cli modules: handles processes and io
-#
-# (c) Copyright 2010 Michael Towers (larch42 at googlemail dot com)
-#
-# This file is part of the larch project.
-#
-# larch 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; either version 2 of the License, or
-# (at your option) any later version.
-#
-# larch 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 larch; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
-#----------------------------------------------------------------------------
-# 2010.07.14
-
-# There was also the vague idea of a web interface, using a sort of state-
-# based approach. Connecting to a running larch process would then require
-# the ability to get the logging history, but presumably not the whole
-# history on every ui update, which would need to be incremental.
-# The logging function would need to be modified to accommodate this.
-
-import os, sys, signal, atexit, __builtin__
-import traceback, pwd
-from subprocess import Popen, PIPE, STDOUT
-import pexpect
-try:
- import json as serialize
-except:
- import simplejson as serialize
-from config import *
-
-def init(app, options, app_quit=None):
- global _options, _quit_function, _log, _controlled, _dontask, _quiet
- _options = options
- _quit_function = app_quit
- _controlled = options.slave
- _dontask = options.force
- _log = None
- _quiet = False if _controlled else options.quiet
-
- atexit.register(sys_quit)
-
-
- def sigint(num, frame):
- """A handler for SIGINT. Tidy up properly and quit.
- """
- errout("INTERRUPTED - killing subprocesses", 0)
- if _sub_process and _sub_process.pid:
- Popen(["pkill", "-g", str(_sub_process.pid)],
- stdout=PIPE).communicate()
- errout("QUITTING", 2)
- signal.signal(signal.SIGINT, sigint)
-
-
- # Check no other instance of the script is running
- if os.path.isfile(LOCKFILE):
- app0 = readfile(LOCKFILE)
- if not query_yn(_(
- "larch (%s) seems to be running already."
- "\nIf you are absolutely sure this is not the case,"
- "\nyou may continue. Otherwise you should cancel."
- "\n\nShall I continue?") % app0):
- sys.exit(102)
- writefile(app, LOCKFILE)
- _log = open(LOGFILE + app, 'w')
-
- # For systems without /sbin and /usr/sbin in the normal PATH
- p = os.environ['PATH']
- ps = p.split(':')
- for px in ('/sbin', '/usr/sbin'):
- if px not in ps:
- p = px + ':' + p
- os.environ['PATH'] = p
-
-
-def _out(text, force=False):
- """Send the string to standard output.
- How it is output depends on the '-s' command line option (whether the
- script is being run on the console or as a subprocess of another script).
- In the latter case the text will be slightly encoded - to avoid newline
- characters - and sent as a single unit.
- Otherwise output the lines as they are, but all lines except
- the first get a '--' prefix.
- """
- lines = text.encode('utf-8').splitlines()
- if _log:
- _log.write(lines[0] + '\n')
- for l in lines[1:]:
- _log.write('--' + l + '\n')
-
- if force or not _quiet:
- if _controlled:
- sys.stdout.write(serialize.dumps(text) + '\n')
- else:
- prefix = ''
- for line in lines:
- sys.stdout.write(prefix + line + '\n')
- prefix = '--'
- sys.stdout.flush()
-
-
-def sys_quit():
- unmount()
- if _quit_function:
- _quit_function()
- if _errorcount:
- _out('!! ' + (_("The backend reported %d failed calls,"
- " you may want to investigate") % _errorcount))
- if _log:
- _log.close()
- os.remove(LOCKFILE)
-
-
-def comment(text):
- _out('##' + text)
-
-
-def query_yn(message, default=False):
- _out('?>' + message)
- result = default
- if _dontask:
- result = True
- elif not _quiet:
- if _controlled:
- result = (raw_input().strip() == '??YES')
-
- else:
- # The character after '_' is the response key
- # The default will be capitalized automatically
- prompt = _("_yes|_no").split('|')
- promptkey = [word[word.index('_') + 1] for word in prompt]
- if default:
- py = prompt[0].upper()
- pn = prompt[1]
- else:
- py = prompt[0]
- pn = prompt[1].upper()
- resp = raw_input(" [ %s / %s ]: " % (py, pn)).strip()
- if resp:
- testkey = promptkey[1] if default else promptkey[0]
- resp == resp.lower()
- if resp == prompt[0]:
- result = True
- elif resp == prompt[1]:
- result = False
- elif testkey in resp:
- result = not default
-
- _out('#>%s' % ('Yes' if result else 'No'))
- return result
-
-
-def errout(message="ERROR", quit=1):
- _out('!>' + message, True)
- if quit:
- sys_quit()
- os._exit(quit)
-
-
-def error0(message):
- errout(message, 0)
-__builtin__.error0 = error0
-
-
-# Catch all unhandled errors.
-def errortrap(type, value, tb):
- etext = "".join(traceback.format_exception(type, value, tb))
- errout(_("Something went wrong:\n") + etext, 100)
-sys.excepthook = errortrap
-
-
-_sub_process = None
-_errorcount = 0
-def runcmd(cmd, filter=None):
- global _sub_process, _errorcount
- _out('>>' + cmd)
- _sub_process = pexpect.spawn(cmd)
- result = []
- line0 = ''
- # A normal end-of-line is '\r\n', so split on '\r' but don't
- # process a line until the next character is available.
- while True:
- try:
- line0 += _sub_process.read_nonblocking(size=256, timeout=None)
- except:
- break
-
- while True:
- lines = line0.split('\r', 1)
- if (len(lines) > 1) and lines[1]:
- line = lines[0]
- line0 = lines[1]
- nl = (line0[0] == '\n')
- if nl:
- # Strip the '\n'
- line0 = line0[1:]
- if filter:
- line = filter(line, nl)
- if line == '/*/':
- continue
- if nl:
- line = line.rstrip()
- _out('>_' + line)
- result.append(line)
- else:
- # Probably a progress line
- if _controlled:
- _out('>-' + line)
- else:
- sys.stdout.write(line + '\r')
- sys.stdout.flush()
-
- else:
- break
-
- _sub_process.close()
- rc = _sub_process.exitstatus
- ok = (rc == 0)
- if not ok:
- _errorcount += 1
- _out(('>?%s' % repr(rc)) + ('' if ok else (' $$$ %s $$$' % cmd)))
- return (ok, result)
-
-
-def script(cmd):
- s = runcmd("%s/%s" % (script_dir, cmd))
- if s[0]:
- return ""
- else:
- return "SCRIPT ERROR: (%s)\n" % cmd + "".join(s[1])
-
-
-def chroot(ip, cmd, mnts=[], filter=None):
- if ip:
- for m in mnts:
- mount("/" + m, "%s/%s" % (ip, m), "--bind")
- cmd = "chroot %s %s" % (ip, cmd)
-
- s = runcmd(cmd, filter)
-
- if ip:
- unmount(["%s/%s" % (ip, m) for m in mnts])
-
- if s[0]:
- if s[1]:
- return s[1]
- else:
- return True
- return False
-
-
-_mounts = []
-def mount(src, dst, opts=""):
- if runcmd("mount %s %s %s" % (opts, src, dst))[0]:
- _mounts.append(dst)
- return True
- return False
-
-
-def unmount(dst=None):
- if dst == None:
- mnts = list(_mounts)
- elif type(dst) in (list, tuple):
- mnts = list(dst)
- else:
- mnts = [dst]
-
- r = True
- for m in mnts:
- if runcmd("umount %s" % m)[0]:
- _mounts.remove(m)
- else:
- r = False
- return r
-
-
-def get_installation_dir():
- return os.path.realpath(_options.idir if _options.idir
- else INSTALLATION)
-
-
-def get_profile():
- """Get the absolute path to the profile folder given its path in any
- acceptable form, including 'user:profile-name'
- """
- pd = (_options.profile if _options.profile
- else base_dir + '/profiles/default')
- p = pd.split(':')
- if len(p) == 1:
- pd = os.path.realpath(pd)
- else:
- try:
- pd = (pwd.getpwnam(p[0])[5] + PROFILE_DIR
- + '/' + p[1])
- except:
- errout(_("Invalid profile: %s") % pd, quit=0)
- raise
- if not os.path.isfile(pd + '/addedpacks'):
- errout(_("Invalid profile folder: %s") % pd)
- return pd
-
-
-
-#+++++++++++++++++++++++++++++++++++++++++
-#Regular expression search strings for progress reports
-import re
-#lit: give []() a \-prefix
-#grp: surround string in ()
-#opt: surround string in []
-
-def _lit(s):
- for c in r'[()]':
- s = s.replace(c, '\\' + c)
- return s
-
-def _grp(s, x=''):
- return '(' + s + ')' + x
-
-def _grp0(s, x=''):
- return '(?:' + s + ')' + x
-
-def _opt(s, x=''):
- return '[' + s + ']' + x
-
-
-_re_pacman = re.compile( _grp0(_lit('(') +
- _grp(_opt('^/', '+') + '/' + _opt('^)', '+')) +
- _lit(')'), '?') +
- _grp('.*?') +
- _lit('[') + _grp(_opt('-#', '+')) + _lit(r']\s+') +
- _grp(_opt('0-9', '+')) +
- '%'
- )
-
-_re_mksquashfs = re.compile(_lit('[.*]') +
- _grp('.* ' +
- _grp(_opt('0-9', '+')) +
- '%')
- )
-
-_re_mkisofs = re.compile(_opt(' 1') + _opt(' \d') + '\d\.\d\d%')
-
-#-----------------------------------------
-class pacman_filter_gen:
- """Return a function to detect and process the progress output of
- pacman.
- """
- def __init__(self):
- self.progress = ''
-
- def __call__(self, line, nl):
- ms = _re_pacman.match(line)
- if ms:
- p = ms.group(3)
- if (self.progress != p) or nl:
- self.progress = p
- if _controlled:
- xfromy = ms.group(1)
- if not xfromy:
- xfromy = ''
- return 'pacman:%s|%s|%s' % (xfromy, ms.group(2),
- ms.group(4))
- if nl:
- sys.stdout.write(' '*80 + '\r')
- return line.rsplit(None, 1)[0]
- else:
- return '/*/'
- return line
-
-
-class mksquashfs_filter_gen:
- """Return a function to detect and process the progress output of
- mksquashfs.
- """
- def __init__(self):
- self.progress = ''
-
- def __call__(self, line, nl):
- ms = _re_mksquashfs.match(line)
- if ms:
- percent = ms.group(2)
- if (self.progress != percent) or nl:
- self.progress = percent
- if _controlled:
- return 'mksquashfs:' + ms.group(1)
- return re.sub(r'=[-\\/|]', '= ', line)
- else:
- return '/*/'
- return line
-
-
-class mkisofs_filter_gen:
- """Return a function to detect and process the progress output of
- mkisofs.
- """
- def __call__(self, line, nl):
- ms = _re_mkisofs.match(line)
- if ms:
- if _controlled:
- return 'mkisofs:' + line
- sys.stdout.write(line + '\r')
- sys.stdout.flush()
- return '/*/'
- return line
-
-
-def readdata(filename):
- return readfile(base_dir + '/data/' + filename)
-
-
-def readfile(fpath):
- try:
- fh = open(fpath)
- text = fh.read()
- fh.close()
- except:
- errout(_("Couldn't read file: %s") % fpath)
- return None
- return text
-
-
-def writefile(text, path):
- try:
- pd = os.path.dirname(path)
- if not os.path.isdir(pd):
- os.makedirs(pd)
- fh = None
- fh = open(path, 'w')
- fh.write(text)
- return True
- except:
- return False
- finally:
- if fh:
- fh.close()
-