Molecule:
- first chunk of code - general infrastructure done - spec file parser done git-svn-id: http://svn.sabayonlinux.org/projects/molecule/trunk@2977 cd1c1023-2f26-0410-ae45-c471fc1f0318
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
# Molecule example .spec file
|
||||
|
||||
# pre chroot command, example, for 32bit chroots on 64bit system, you always have to append "linux32"
|
||||
# prechroot: linux32
|
||||
|
||||
# Release string
|
||||
# release_string: Sabayon Linux
|
||||
|
||||
# Release Version
|
||||
# release_version: 4
|
||||
|
||||
# Release Version string description
|
||||
# release_desc: Lite MCE
|
||||
|
||||
# Release file (inside chroot)
|
||||
# release_file: /etc/sabayon-edition
|
||||
|
||||
# Source chroot directory, where files are pulled from
|
||||
# source_chroot: /var/tmp/catalyst/tmp/stage1-amd64-2006.0
|
||||
|
||||
# Destination chroot directory, where files are pushed to before creating the squashfs image
|
||||
# destination_chroot: /var/tmp/catalyst/tmp/stage1-amd64-2006.0/default/livecd-stage2-amd64-2006.0
|
||||
|
||||
# Merge directory with destination chroot
|
||||
# merge_destination_chroot: /path/to/your/chroot/overlay
|
||||
|
||||
# Outer chroot script command, to be executed outside destination chroot before packing it
|
||||
# outer_chroot_script: /path/to/script/to/be/executed/outside
|
||||
|
||||
# Inner chroot script command, to be executed inside destination chroot before packing it
|
||||
# inner_chroot_script: /path/to/script/to/be/executed/inside
|
||||
|
||||
# Destination LiveCD root directory, where files are placed before getting mkisofs'ed
|
||||
# destination_livecd_root: /path/to/dest/livecd
|
||||
|
||||
# Merge directory with destination LiveCD root
|
||||
# merge_livecd_root: /path/to/your/configured/bootloader dir
|
||||
|
||||
# Extra mksquashfs parameters
|
||||
# extra_mksquashfs_parameters:
|
||||
|
||||
# Extra mkisofs parameters, perhaps something to include/use your bootloader
|
||||
# extra_mkisofs_parameters:
|
||||
|
||||
# Destination directory for the ISO image path
|
||||
# destination_iso_directory:
|
||||
|
||||
# Destination ISO image name, call whatever you want.iso, not mandatory
|
||||
# destination_iso_image_name:
|
||||
|
||||
# Directories to remove completely (comma separated)
|
||||
# directories_to_remove: /path/to/abc, /path/to/xyz,
|
||||
|
||||
# Directories to empty (comma separated)
|
||||
# directories_to_empty: /path/to/abc, /path/to/xyz,
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/python -O
|
||||
# -*- coding: iso-8859-1 -*-
|
||||
# Molecule Disc Image builder for Sabayon Linux
|
||||
# Copyright (C) 2009 Fabio Erculiani
|
||||
#
|
||||
# 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; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
import sys
|
||||
sys.path.insert(0,'molecule/')
|
||||
import molecule.settings
|
||||
import molecule.cmdline
|
||||
|
||||
molecule_data = molecule.cmdline.parse()
|
||||
if not molecule_data:
|
||||
molecule.cmdline.print_help()
|
||||
raise SystemExit(1)
|
||||
|
||||
print "valid",molecule_data
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/python -O
|
||||
# -*- coding: iso-8859-1 -*-
|
||||
# Molecule Disc Image builder for Sabayon Linux
|
||||
# Copyright (C) 2009 Fabio Erculiani
|
||||
#
|
||||
# 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; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
import molecule.settings
|
||||
Config = molecule.settings.Configuration()
|
||||
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/python -O
|
||||
# -*- coding: iso-8859-1 -*-
|
||||
# Molecule Disc Image builder for Sabayon Linux
|
||||
# Copyright (C) 2009 Fabio Erculiani
|
||||
#
|
||||
# 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; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import molecule.utils
|
||||
import molecule.output
|
||||
from molecule.i18n import _
|
||||
from molecule import Config
|
||||
from molecule.settings import SpecParser
|
||||
|
||||
def parse():
|
||||
args_to_remove = ["--nocolor"]
|
||||
data = {}
|
||||
|
||||
myargs = sys.argv[1:]
|
||||
|
||||
if "--help" in myargs:
|
||||
return data
|
||||
if "--nocolor" in myargs:
|
||||
molecule.output.nocolor()
|
||||
|
||||
for arg in args_to_remove:
|
||||
if arg in myargs: myargs.remove(arg)
|
||||
|
||||
for el in myargs:
|
||||
if os.path.isfile(el) and os.access(el,os.R_OK):
|
||||
obj = SpecParser(el)
|
||||
el_data = obj.parse()
|
||||
del obj
|
||||
if el_data: data[el] = el_data
|
||||
return data
|
||||
|
||||
def print_help():
|
||||
help_data = [
|
||||
None,
|
||||
(0," ~ Molecule %s ~ " % (Config.get('version'),) ,1,'Disc Image builder for Sabayon Linux - (C) %s' % (molecule.utils.get_year(),) ),
|
||||
None,
|
||||
(0,_('Basic Options'),0,None),
|
||||
None,
|
||||
(1,'--help',2,_('this output')),
|
||||
(1,'--nocolor',1,_('disable colorized output')),
|
||||
None,
|
||||
(0,_('Application Options'),0,None),
|
||||
(1,'<spec file path 1> <spec file path 2> ...',1,_('execute against specified specification files')),
|
||||
None,
|
||||
]
|
||||
molecule.output.print_menu(help_data)
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/python -O
|
||||
# -*- coding: iso-8859-1 -*-
|
||||
# Molecule Disc Image builder for Sabayon Linux
|
||||
# Copyright (C) 2009 Fabio Erculiani
|
||||
#
|
||||
# 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; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
class MoleculeException(Exception):
|
||||
"""General superclass for Entropy exceptions"""
|
||||
def __init__(self,value):
|
||||
self.value = value[:]
|
||||
|
||||
def __str__(self):
|
||||
if isinstance(self.value, basestring):
|
||||
return self.value
|
||||
else:
|
||||
return repr(self.value)
|
||||
|
||||
class EnvironmentError(MoleculeException):
|
||||
"""Environment error, self explanatory"""
|
||||
|
||||
class SpecFileError(MoleculeException):
|
||||
"""Error inside spec file"""
|
||||
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/python
|
||||
# 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; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# 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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
"""
|
||||
License: GPL
|
||||
Author: Fabio Erculiani <lxnay@sabayonlinux.org>
|
||||
"""
|
||||
_LOCALE = None
|
||||
try:
|
||||
import gettext
|
||||
import os
|
||||
gettext.bindtextdomain('molecule', '/usr/share/locale')
|
||||
gettext.textdomain('molecule')
|
||||
gettext.install('molecule', unicode = True)
|
||||
_ = _
|
||||
|
||||
_LOCALE_FULL = os.getenv('LC_ALL')
|
||||
if _LOCALE_FULL == None:
|
||||
_LOCALE_FULL = os.getenv('LANG')
|
||||
if _LOCALE_FULL == None:
|
||||
_LOCALE_FULL = os.getenv('LANGUAGE')
|
||||
|
||||
if _LOCALE_FULL:
|
||||
_LOCALE = _LOCALE_FULL.split('.')[0]
|
||||
_LOCALE = _LOCALE.split('_')[0]
|
||||
_LOCALE = _LOCALE.lower()
|
||||
|
||||
except:
|
||||
def _(s):
|
||||
return s
|
||||
@@ -0,0 +1,402 @@
|
||||
#!/usr/bin/python -O
|
||||
# -*- coding: iso-8859-1 -*-
|
||||
# Molecule Disc Image builder for Sabayon Linux
|
||||
# Copyright (C) 2009 Fabio Erculiani
|
||||
#
|
||||
# Copyright 1998-2004 Gentoo Foundation
|
||||
# # $Id: output.py 4906 2006-11-01 23:55:29Z zmedico $
|
||||
# Copyright (C) 2007-2008 Fabio Erculiani
|
||||
#
|
||||
# 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; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
from molecule.i18n import _
|
||||
import sys, os
|
||||
import curses
|
||||
stuff = {}
|
||||
stuff['cols'] = 30
|
||||
try:
|
||||
curses.setupterm()
|
||||
stuff['cols'] = curses.tigetnum('cols')
|
||||
except:
|
||||
pass
|
||||
stuff['cleanline'] = ""
|
||||
def setcols():
|
||||
stuff['cleanline'] = ""
|
||||
count = stuff['cols']
|
||||
while count:
|
||||
stuff['cleanline'] += ' '
|
||||
count -= 1
|
||||
setcols()
|
||||
stuff['cursor'] = False
|
||||
stuff['ESC'] = chr(27)
|
||||
|
||||
havecolor=1
|
||||
global dotitles
|
||||
dotitles=1
|
||||
|
||||
esc_seq = "\x1b["
|
||||
|
||||
g_attr = {}
|
||||
g_attr["normal"] = 0
|
||||
|
||||
g_attr["bold"] = 1
|
||||
g_attr["faint"] = 2
|
||||
g_attr["standout"] = 3
|
||||
g_attr["underline"] = 4
|
||||
g_attr["blink"] = 5
|
||||
g_attr["overline"] = 6 # Why is overline actually useful?
|
||||
g_attr["reverse"] = 7
|
||||
g_attr["invisible"] = 8
|
||||
|
||||
g_attr["no-attr"] = 22
|
||||
g_attr["no-standout"] = 23
|
||||
g_attr["no-underline"] = 24
|
||||
g_attr["no-blink"] = 25
|
||||
g_attr["no-overline"] = 26
|
||||
g_attr["no-reverse"] = 27
|
||||
# 28 isn't defined?
|
||||
# 29 isn't defined?
|
||||
g_attr["black"] = 30
|
||||
g_attr["red"] = 31
|
||||
g_attr["green"] = 32
|
||||
g_attr["yellow"] = 33
|
||||
g_attr["blue"] = 34
|
||||
g_attr["magenta"] = 35
|
||||
g_attr["cyan"] = 36
|
||||
g_attr["white"] = 37
|
||||
# 38 isn't defined?
|
||||
g_attr["default"] = 39
|
||||
g_attr["bg_black"] = 40
|
||||
g_attr["bg_red"] = 41
|
||||
g_attr["bg_green"] = 42
|
||||
g_attr["bg_yellow"] = 43
|
||||
g_attr["bg_blue"] = 44
|
||||
g_attr["bg_magenta"] = 45
|
||||
g_attr["bg_cyan"] = 46
|
||||
g_attr["bg_white"] = 47
|
||||
g_attr["bg_default"] = 49
|
||||
|
||||
|
||||
def color(fg, bg="default", attr=["normal"]):
|
||||
mystr = esc_seq[:] + "%02d" % g_attr[fg]
|
||||
for x in [bg]+attr:
|
||||
mystr += ";%02d" % g_attr[x]
|
||||
return mystr+"m"
|
||||
|
||||
|
||||
|
||||
codes={}
|
||||
codes["reset"] = esc_seq + "39;49;00m"
|
||||
|
||||
codes["bold"] = esc_seq + "01m"
|
||||
codes["faint"] = esc_seq + "02m"
|
||||
codes["standout"] = esc_seq + "03m"
|
||||
codes["underline"] = esc_seq + "04m"
|
||||
codes["blink"] = esc_seq + "05m"
|
||||
codes["overline"] = esc_seq + "06m" # Who made this up? Seriously.
|
||||
|
||||
ansi_color_codes = []
|
||||
for x in xrange(30, 38):
|
||||
ansi_color_codes.append("%im" % x)
|
||||
ansi_color_codes.append("%i;01m" % x)
|
||||
|
||||
rgb_ansi_colors = ['0x000000', '0x555555', '0xAA0000', '0xFF5555', '0x00AA00',
|
||||
'0x55FF55', '0xAA5500', '0xFFFF55', '0x0000AA', '0x5555FF', '0xAA00AA',
|
||||
'0xFF55FF', '0x00AAAA', '0x55FFFF', '0xAAAAAA', '0xFFFFFF']
|
||||
|
||||
for x in xrange(len(rgb_ansi_colors)):
|
||||
codes[rgb_ansi_colors[x]] = esc_seq + ansi_color_codes[x]
|
||||
|
||||
del x
|
||||
|
||||
codes["black"] = codes["0x000000"]
|
||||
codes["darkgray"] = codes["0x555555"]
|
||||
|
||||
codes["red"] = codes["0xFF5555"]
|
||||
codes["darkred"] = codes["0xAA0000"]
|
||||
|
||||
codes["green"] = codes["0x55FF55"]
|
||||
codes["darkgreen"] = codes["0x00AA00"]
|
||||
|
||||
codes["yellow"] = codes["0xFFFF55"]
|
||||
codes["brown"] = codes["0xAA5500"]
|
||||
|
||||
codes["blue"] = codes["0x5555FF"]
|
||||
codes["darkblue"] = codes["0x0000AA"]
|
||||
|
||||
codes["fuchsia"] = codes["0xFF55FF"]
|
||||
codes["purple"] = codes["0xAA00AA"]
|
||||
|
||||
codes["turquoise"] = codes["0x55FFFF"]
|
||||
codes["teal"] = codes["0x00AAAA"]
|
||||
|
||||
codes["white"] = codes["0xFFFFFF"]
|
||||
codes["lightgray"] = codes["0xAAAAAA"]
|
||||
|
||||
codes["darkteal"] = codes["turquoise"]
|
||||
codes["darkyellow"] = codes["brown"]
|
||||
codes["fuscia"] = codes["fuchsia"]
|
||||
codes["white"] = codes["bold"]
|
||||
|
||||
# Colors from /sbin/functions.sh
|
||||
codes["GOOD"] = codes["green"]
|
||||
codes["WARN"] = codes["yellow"]
|
||||
codes["BAD"] = codes["red"]
|
||||
codes["HILITE"] = codes["teal"]
|
||||
codes["BRACKET"] = codes["blue"]
|
||||
|
||||
# Portage functions
|
||||
codes["INFORM"] = codes["darkgreen"]
|
||||
codes["UNMERGE_WARN"] = codes["red"]
|
||||
codes["MERGE_LIST_PROGRESS"] = codes["yellow"]
|
||||
|
||||
def xtermTitle(mystr, raw=False):
|
||||
if dotitles and "TERM" in os.environ and sys.stderr.isatty():
|
||||
myt=os.environ["TERM"]
|
||||
legal_terms = ["xterm","Eterm","aterm","rxvt","screen","kterm","rxvt-unicode","gnome"]
|
||||
if myt in legal_terms:
|
||||
if not raw:
|
||||
mystr = "\x1b]0;%s\x07" % mystr
|
||||
try:
|
||||
sys.stderr.write(mystr)
|
||||
except UnicodeEncodeError:
|
||||
sys.stderr.write(mystr.encode('utf-8'))
|
||||
sys.stderr.flush()
|
||||
|
||||
default_xterm_title = None
|
||||
|
||||
def xtermTitleReset():
|
||||
global default_xterm_title
|
||||
if default_xterm_title is None:
|
||||
prompt_command = os.getenv('PROMPT_COMMAND')
|
||||
if prompt_command == "":
|
||||
default_xterm_title = ""
|
||||
elif prompt_command is not None:
|
||||
import commands
|
||||
default_xterm_title = commands.getoutput(prompt_command)
|
||||
else:
|
||||
pwd = os.getenv('PWD','')
|
||||
home = os.getenv('HOME', '')
|
||||
if home != '' and pwd.startswith(home):
|
||||
pwd = '~' + pwd[len(home):]
|
||||
default_xterm_title = '\x1b]0;%s@%s:%s\x07' % (
|
||||
os.getenv('LOGNAME', ''), os.getenv('HOSTNAME', '').split('.', 1)[0], pwd)
|
||||
xtermTitle(default_xterm_title, raw=True)
|
||||
|
||||
def notitles():
|
||||
"turn off title setting"
|
||||
global dotitles
|
||||
dotitles=0
|
||||
|
||||
def nocolor():
|
||||
"turn off colorization"
|
||||
os.environ['MOL_NO_COLOR'] = "1"
|
||||
global havecolor
|
||||
havecolor=0
|
||||
|
||||
nc = os.getenv("MOL_NO_COLOR")
|
||||
if nc:
|
||||
nocolor()
|
||||
|
||||
def resetColor():
|
||||
return codes["reset"]
|
||||
|
||||
def colorize(color_key, text):
|
||||
global havecolor
|
||||
if havecolor:
|
||||
return codes[color_key] + text + codes["reset"]
|
||||
else:
|
||||
return text
|
||||
|
||||
compat_functions_colors = ["bold","white","teal","turquoise","darkteal",
|
||||
"fuscia","fuchsia","purple","blue","darkblue","green","darkgreen","yellow",
|
||||
"brown","darkyellow","red","darkred"]
|
||||
|
||||
def create_color_func(color_key):
|
||||
def derived_func(*args):
|
||||
newargs = list(args)
|
||||
newargs.insert(0, color_key)
|
||||
return colorize(*newargs)
|
||||
return derived_func
|
||||
|
||||
for c in compat_functions_colors:
|
||||
setattr(sys.modules[__name__], c, create_color_func(c))
|
||||
|
||||
def print_menu(data):
|
||||
|
||||
def orig_myfunc(x):
|
||||
return x
|
||||
def orig_myfunc_desc(x):
|
||||
return x
|
||||
|
||||
for item in data:
|
||||
|
||||
myfunc = orig_myfunc
|
||||
myfunc_desc = orig_myfunc_desc
|
||||
|
||||
if not item:
|
||||
writechar("\n")
|
||||
else:
|
||||
n_ident = item[0]
|
||||
name = item[1]
|
||||
n_d_ident = item[2]
|
||||
desc = item[3]
|
||||
|
||||
if n_ident == 0:
|
||||
writechar(" ")
|
||||
# setup identation
|
||||
while n_ident > 0:
|
||||
n_ident -= 1
|
||||
writechar("\t")
|
||||
n_ident = item[0]
|
||||
|
||||
# write name
|
||||
if n_ident == 0:
|
||||
myfunc = darkgreen
|
||||
elif n_ident == 1:
|
||||
myfunc = blue
|
||||
myfunc_desc = darkgreen
|
||||
elif n_ident == 2:
|
||||
if not name.startswith("--"):
|
||||
myfunc = red
|
||||
myfunc_desc = brown
|
||||
elif n_ident == 3:
|
||||
myfunc = darkblue
|
||||
myfunc_desc = purple
|
||||
try:
|
||||
print myfunc(name),
|
||||
except UnicodeEncodeError:
|
||||
print myfunc(name.encode('utf-8')),
|
||||
|
||||
# write desc
|
||||
if desc:
|
||||
while n_d_ident > 0:
|
||||
n_d_ident -= 1
|
||||
writechar("\t")
|
||||
try:
|
||||
print myfunc_desc(desc),
|
||||
except UnicodeEncodeError:
|
||||
print myfunc_desc(desc.encode('utf-8')),
|
||||
writechar("\n")
|
||||
|
||||
def reset_cursor():
|
||||
if havecolor:
|
||||
sys.stdout.write(stuff['ESC'] + '[2K')
|
||||
flush_stdouterr()
|
||||
|
||||
def flush_stdouterr():
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
|
||||
def print_error(msg, back = False, flush = True):
|
||||
if not back: setcols()
|
||||
reset_cursor()
|
||||
writechar("\r")
|
||||
if back:
|
||||
try:
|
||||
print darkred(">>"),msg,
|
||||
except UnicodeEncodeError:
|
||||
print darkred(">>"),msg.encode('utf-8'),
|
||||
else:
|
||||
try:
|
||||
print darkred(">>"),msg
|
||||
except UnicodeEncodeError:
|
||||
print darkred(">>"),msg.encode('utf-8')
|
||||
if flush:
|
||||
flush_stdouterr()
|
||||
|
||||
def print_info(msg, back = False, flush = True):
|
||||
if not back:
|
||||
setcols()
|
||||
reset_cursor()
|
||||
writechar("\r")
|
||||
if back:
|
||||
try:
|
||||
print darkgreen(">>"),msg,
|
||||
except UnicodeEncodeError:
|
||||
print darkgreen(">>"),msg.encode('utf-8'),
|
||||
else:
|
||||
try:
|
||||
print darkgreen(">>"),msg
|
||||
except UnicodeEncodeError:
|
||||
print darkgreen(">>"),msg.encode('utf-8')
|
||||
if flush:
|
||||
flush_stdouterr()
|
||||
|
||||
def print_warning(msg, back = False, flush = True):
|
||||
if not back: setcols()
|
||||
reset_cursor()
|
||||
writechar("\r")
|
||||
if back:
|
||||
try:
|
||||
print red(">>"),msg,
|
||||
except UnicodeEncodeError:
|
||||
print red(">>"),msg.encode('utf-8'),
|
||||
else:
|
||||
try:
|
||||
print red(">>"),msg
|
||||
except UnicodeEncodeError:
|
||||
print red(">>"),msg.encode('utf-8')
|
||||
if flush:
|
||||
flush_stdouterr()
|
||||
|
||||
def print_generic(msg): # here we'll wrap any nice formatting
|
||||
writechar("\r")
|
||||
try:
|
||||
print msg
|
||||
except UnicodeEncodeError:
|
||||
print msg.encode('utf-8')
|
||||
flush_stdouterr()
|
||||
|
||||
def writechar(char):
|
||||
try:
|
||||
sys.stdout.write(char)
|
||||
sys.stdout.flush()
|
||||
except IOError, e:
|
||||
if e.errno == 32:
|
||||
return
|
||||
raise
|
||||
|
||||
def readtext(request, password = False):
|
||||
xtermTitle(_("Molecule needs your attention"))
|
||||
if password:
|
||||
from getpass import getpass
|
||||
try:
|
||||
text = getpass(request+" ")
|
||||
except UnicodeEncodeError:
|
||||
text = getpass(request.encode('utf-8')+" ")
|
||||
else:
|
||||
try:
|
||||
print request,"",
|
||||
except UnicodeEncodeError:
|
||||
print request.encode('utf-8'),"",
|
||||
flush_stdouterr()
|
||||
text = my_raw_input()
|
||||
return text
|
||||
|
||||
def my_raw_input(txt = ''):
|
||||
if txt:
|
||||
try:
|
||||
print darkgreen(txt),
|
||||
except UnicodeEncodeError:
|
||||
print darkgreen(txt.encode('utf-8')),
|
||||
flush_stdouterr()
|
||||
response = ''
|
||||
while 1:
|
||||
y = sys.stdin.read(1)
|
||||
if y in ('\n','\r',): break
|
||||
response += y
|
||||
flush_stdouterr()
|
||||
return response
|
||||
@@ -0,0 +1,270 @@
|
||||
#!/usr/bin/python -O
|
||||
# -*- coding: iso-8859-1 -*-
|
||||
# Molecule Disc Image builder for Sabayon Linux
|
||||
# Copyright (C) 2009 Fabio Erculiani
|
||||
#
|
||||
# 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; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
from __future__ import with_statement
|
||||
import os
|
||||
import threading
|
||||
from molecule.exception import SpecFileError, EnvironmentError
|
||||
import molecule.utils
|
||||
|
||||
class Dictionary:
|
||||
|
||||
def __init__(self):
|
||||
self._settings = {}
|
||||
self.L = threading.Lock()
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
with self.L:
|
||||
self._settings[key] = value
|
||||
|
||||
def __getitem__(self, key):
|
||||
with self.L:
|
||||
return self._settings[key]
|
||||
|
||||
def __contains__(self, key):
|
||||
with self.L:
|
||||
return key in self._settings
|
||||
|
||||
def __cmp__(self, other):
|
||||
with self.L:
|
||||
return cmp(self._settings,other)
|
||||
|
||||
def __str__(self):
|
||||
with self.L:
|
||||
return str(self._settings)
|
||||
|
||||
def get(self, key):
|
||||
with self.L:
|
||||
return self._settings.get(key)
|
||||
|
||||
def has_key(self, key):
|
||||
with self.L:
|
||||
return self._settings.has_key(key)
|
||||
|
||||
def clear(self):
|
||||
with self.L:
|
||||
self._settings.clear()
|
||||
|
||||
def keys(self):
|
||||
with self.L:
|
||||
return self._settings.keys()
|
||||
|
||||
class Constants(Dictionary):
|
||||
|
||||
def __init__(self):
|
||||
Dictionary.__init__(self)
|
||||
self.load()
|
||||
|
||||
def load(self):
|
||||
with self.L:
|
||||
ETC_DIR = '/etc'
|
||||
CONFIG_FILE_NAME = 'molecule.conf'
|
||||
|
||||
mysettings = {
|
||||
'config_file': os.path.join(ETC_DIR, CONFIG_FILE_NAME),
|
||||
}
|
||||
|
||||
self._settings.clear()
|
||||
self._settings.update(mysettings)
|
||||
|
||||
class Configuration(Dictionary):
|
||||
|
||||
def __init__(self):
|
||||
Dictionary.__init__(self)
|
||||
self.Constants = Constants()
|
||||
self.load()
|
||||
|
||||
def load(self, mysettings = {}):
|
||||
with self.L:
|
||||
settings = {
|
||||
'version': "0.1",
|
||||
'chroot_compressor': "mksquashfs",
|
||||
'iso_builder': "mkisofs",
|
||||
'iso_builder_builtin_args': ["-J","-R","-l","-no-emul-boot","-boot-load-size","4","-udf","-boot-info-table"],
|
||||
}
|
||||
self._settings.clear()
|
||||
self._settings.update(settings)
|
||||
self._settings.update(mysettings)
|
||||
|
||||
paths_to_check = ["chroot_compressor","iso_builder"]
|
||||
for key in paths_to_check:
|
||||
molecule.utils.valid_exec_check(self.get(key))
|
||||
|
||||
class SpecParser:
|
||||
|
||||
def __init__(self, filepath):
|
||||
|
||||
def ne_string(x):
|
||||
return x
|
||||
|
||||
def always_valid(*args):
|
||||
return True
|
||||
|
||||
def valid_path(x):
|
||||
return os.path.lexists(x)
|
||||
|
||||
def valid_file(x):
|
||||
return os.path.isfile(x)
|
||||
|
||||
def valid_dir(x):
|
||||
return os.path.isdir(x)
|
||||
|
||||
def ve_string_stripper(x):
|
||||
return x.strip()
|
||||
|
||||
def ve_string_splitter(x):
|
||||
return x.strip().split()
|
||||
|
||||
def valid_exec(x):
|
||||
molecule.utils.is_exec_available(x)
|
||||
return True
|
||||
|
||||
def valid_ascii(x):
|
||||
try:
|
||||
x = str(x)
|
||||
return x
|
||||
except (UnicodeDecodeError,UnicodeEncodeError,):
|
||||
return ''
|
||||
|
||||
def valid_path_string(x):
|
||||
try:
|
||||
os.path.split(x)
|
||||
except OSError:
|
||||
return False
|
||||
return True
|
||||
|
||||
def valid_path_list(x):
|
||||
return [x for x in x.split(",") if valid_path_string(x)]
|
||||
|
||||
self.vital_parameters = [
|
||||
"release_string",
|
||||
"source_chroot",
|
||||
"destination_iso_directory",
|
||||
]
|
||||
self.parser_data_path = {
|
||||
'prechroot': {
|
||||
'cb': valid_exec,
|
||||
've': ve_string_stripper,
|
||||
},
|
||||
'release_string': {
|
||||
'cb': ne_string, # validation callback
|
||||
've': ve_string_stripper, # value extractor
|
||||
},
|
||||
'release_version': {
|
||||
'cb': ne_string,
|
||||
've': ve_string_stripper,
|
||||
},
|
||||
'release_desc': {
|
||||
'cb': ne_string,
|
||||
've': ve_string_stripper,
|
||||
},
|
||||
'release_file': {
|
||||
'cb': ne_string,
|
||||
've': ve_string_stripper,
|
||||
},
|
||||
'source_chroot': {
|
||||
'cb': valid_dir,
|
||||
've': ve_string_stripper,
|
||||
},
|
||||
'destination_chroot': {
|
||||
'cb': valid_path_string,
|
||||
've': ve_string_stripper,
|
||||
},
|
||||
'merge_destination_chroot': {
|
||||
'cb': valid_dir,
|
||||
've': ve_string_stripper,
|
||||
},
|
||||
'outer_chroot_script': {
|
||||
'cb': valid_exec,
|
||||
've': ve_string_stripper,
|
||||
},
|
||||
'inner_chroot_script': {
|
||||
'cb': valid_path_string,
|
||||
've': ve_string_stripper,
|
||||
},
|
||||
'destination_livecd_root': {
|
||||
'cb': valid_path_string,
|
||||
've': ve_string_stripper,
|
||||
},
|
||||
'merge_livecd_root': {
|
||||
'cb': valid_dir,
|
||||
've': ve_string_stripper,
|
||||
},
|
||||
'extra_mksquashfs_parameters': {
|
||||
'cb': always_valid,
|
||||
've': ve_string_splitter,
|
||||
},
|
||||
'extra_mkisofs_parameters': {
|
||||
'cb': always_valid,
|
||||
've': ve_string_splitter,
|
||||
},
|
||||
'destination_iso_directory': {
|
||||
'cb': valid_dir,
|
||||
've': ve_string_stripper,
|
||||
},
|
||||
'destination_iso_image_name': {
|
||||
'cb': valid_ascii,
|
||||
've': ve_string_stripper,
|
||||
},
|
||||
'directories_to_remove': {
|
||||
'cb': valid_path_list,
|
||||
've': ve_string_stripper,
|
||||
},
|
||||
'directories_to_empty': {
|
||||
'cb': valid_path_list,
|
||||
've': ve_string_stripper,
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
self.filepath = filepath[:]
|
||||
|
||||
def parse(self):
|
||||
mydict = {}
|
||||
data = self.__generic_parser(self.filepath)
|
||||
for line in data:
|
||||
try:
|
||||
key, value = line.split(":",1)
|
||||
except (ValueError, IndexError,):
|
||||
continue
|
||||
key = key.strip()
|
||||
check_dict = self.parser_data_path.get(key)
|
||||
if not isinstance(check_dict,dict): continue
|
||||
value = check_dict['ve'](value)
|
||||
if not check_dict['cb'](value): continue
|
||||
mydict[key] = value
|
||||
self.validate_parse(mydict)
|
||||
return mydict.copy()
|
||||
|
||||
def validate_parse(self, mydata):
|
||||
for param in self.vital_parameters:
|
||||
if param not in mydata:
|
||||
raise SpecFileError("SpecFileError: '%s' missing or invalid '%s' parameter, it's vital. Your specification file is incomplete!" % (self.filepath,param,))
|
||||
|
||||
def __generic_parser(self, filepath):
|
||||
with open(filepath,"r") as f:
|
||||
data = []
|
||||
content = f.readlines()
|
||||
f.close()
|
||||
# filter comments and white lines
|
||||
content = [x.strip().rsplit("#",1)[0].strip() for x in content if not x.startswith("#") and x.strip()]
|
||||
for line in content:
|
||||
if line in data: continue
|
||||
data.append(line)
|
||||
return data
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/python -O
|
||||
# -*- coding: iso-8859-1 -*-
|
||||
# Molecule Disc Image builder for Sabayon Linux
|
||||
# Copyright (C) 2009 Fabio Erculiani
|
||||
#
|
||||
# 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; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
from __future__ import with_statement
|
||||
import os
|
||||
import time
|
||||
import subprocess
|
||||
from molecule.exception import EnvironmentError
|
||||
|
||||
def get_year():
|
||||
return time.strftime("%Y")
|
||||
|
||||
def valid_exec_check(path):
|
||||
with open("/dev/null","w") as f:
|
||||
p = subprocess.Popen([path], stdout = f, stderr = f)
|
||||
rc = p.wait()
|
||||
if rc == 127:
|
||||
raise EnvironmentError("EnvironmentError: %s not found" % (path,))
|
||||
|
||||
def is_exec_available(exec_name):
|
||||
paths = os.getenv("PATH")
|
||||
if not paths: return False
|
||||
paths = paths.split(":")
|
||||
for path in paths:
|
||||
path = os.path.join(path,exec_name)
|
||||
if os.path.isfile(path) and os.access(path,os.X_OK):
|
||||
return True
|
||||
return False
|
||||
Reference in New Issue
Block a user