summaryrefslogtreecommitdiffstats
path: root/yocto-poky/bitbake/lib/bb
diff options
context:
space:
mode:
Diffstat (limited to 'yocto-poky/bitbake/lib/bb')
-rw-r--r--yocto-poky/bitbake/lib/bb/__init__.py18
-rw-r--r--yocto-poky/bitbake/lib/bb/build.py55
-rw-r--r--yocto-poky/bitbake/lib/bb/cache.py31
-rw-r--r--yocto-poky/bitbake/lib/bb/checksum.py49
-rw-r--r--yocto-poky/bitbake/lib/bb/codeparser.py34
-rw-r--r--yocto-poky/bitbake/lib/bb/command.py1
-rw-r--r--yocto-poky/bitbake/lib/bb/cooker.py141
-rw-r--r--yocto-poky/bitbake/lib/bb/cookerdata.py11
-rw-r--r--yocto-poky/bitbake/lib/bb/data.py48
-rw-r--r--yocto-poky/bitbake/lib/bb/data_smart.py29
-rw-r--r--yocto-poky/bitbake/lib/bb/event.py15
-rw-r--r--yocto-poky/bitbake/lib/bb/fetch2/__init__.py240
-rw-r--r--yocto-poky/bitbake/lib/bb/fetch2/git.py21
-rw-r--r--yocto-poky/bitbake/lib/bb/fetch2/gitsm.py9
-rw-r--r--yocto-poky/bitbake/lib/bb/fetch2/local.py1
-rw-r--r--yocto-poky/bitbake/lib/bb/fetch2/npm.py284
-rw-r--r--yocto-poky/bitbake/lib/bb/fetch2/osc.py12
-rw-r--r--yocto-poky/bitbake/lib/bb/fetch2/wget.py118
-rwxr-xr-xyocto-poky/bitbake/lib/bb/main.py22
-rw-r--r--yocto-poky/bitbake/lib/bb/methodpool.py15
-rw-r--r--yocto-poky/bitbake/lib/bb/parse/__init__.py4
-rw-r--r--yocto-poky/bitbake/lib/bb/parse/ast.py77
-rw-r--r--yocto-poky/bitbake/lib/bb/parse/parse_py/BBHandler.py23
-rw-r--r--yocto-poky/bitbake/lib/bb/persist_data.py1
-rw-r--r--yocto-poky/bitbake/lib/bb/providers.py105
-rw-r--r--yocto-poky/bitbake/lib/bb/runqueue.py119
-rw-r--r--yocto-poky/bitbake/lib/bb/server/__init__.py3
-rw-r--r--yocto-poky/bitbake/lib/bb/server/process.py14
-rw-r--r--yocto-poky/bitbake/lib/bb/server/xmlrpc.py18
-rw-r--r--yocto-poky/bitbake/lib/bb/siggen.py111
-rw-r--r--yocto-poky/bitbake/lib/bb/taskdata.py45
-rw-r--r--yocto-poky/bitbake/lib/bb/tests/codeparser.py7
-rw-r--r--yocto-poky/bitbake/lib/bb/tests/data.py13
-rw-r--r--yocto-poky/bitbake/lib/bb/tests/fetch.py145
-rw-r--r--yocto-poky/bitbake/lib/bb/tests/utils.py24
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/buildinfohelper.py367
-rwxr-xr-xyocto-poky/bitbake/lib/bb/ui/crumbs/builddetailspage.py437
-rwxr-xr-xyocto-poky/bitbake/lib/bb/ui/crumbs/builder.py1475
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/buildmanager.py455
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/hig/advancedsettingsdialog.py341
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/hig/parsingwarningsdialog.py163
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/hig/proxydetailsdialog.py90
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/hig/retrieveimagedialog.py51
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/hig/saveimagedialog.py159
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/hig/simplesettingsdialog.py891
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/hobeventhandler.py645
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/hoblistmodel.py903
-rwxr-xr-xyocto-poky/bitbake/lib/bb/ui/crumbs/hobpages.py128
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/imageconfigurationpage.py561
-rwxr-xr-xyocto-poky/bitbake/lib/bb/ui/crumbs/imagedetailspage.py669
-rwxr-xr-xyocto-poky/bitbake/lib/bb/ui/crumbs/packageselectionpage.py355
-rwxr-xr-xyocto-poky/bitbake/lib/bb/ui/crumbs/recipeselectionpage.py335
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/sanitycheckpage.py85
-rwxr-xr-xyocto-poky/bitbake/lib/bb/ui/hob.py109
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/knotty.py62
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/puccho.py425
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/toasterui.py109
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/uievent.py30
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/uihelper.py41
-rw-r--r--yocto-poky/bitbake/lib/bb/utils.py104
60 files changed, 1734 insertions, 9119 deletions
diff --git a/yocto-poky/bitbake/lib/bb/__init__.py b/yocto-poky/bitbake/lib/bb/__init__.py
index ac62d262c..502ad839e 100644
--- a/yocto-poky/bitbake/lib/bb/__init__.py
+++ b/yocto-poky/bitbake/lib/bb/__init__.py
@@ -21,7 +21,7 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-__version__ = "1.28.0"
+__version__ = "1.30.0"
import sys
if sys.version_info < (2, 7, 3):
@@ -70,6 +70,8 @@ logger = logging.getLogger("BitBake")
logger.addHandler(NullHandler())
logger.setLevel(logging.DEBUG - 2)
+mainlogger = logging.getLogger("BitBake.Main")
+
# This has to be imported after the setLoggerClass, as the import of bb.msg
# can result in construction of the various loggers.
import bb.msg
@@ -79,26 +81,26 @@ sys.modules['bb.fetch'] = sys.modules['bb.fetch2']
# Messaging convenience functions
def plain(*args):
- logger.plain(''.join(args))
+ mainlogger.plain(''.join(args))
def debug(lvl, *args):
if isinstance(lvl, basestring):
- logger.warn("Passed invalid debug level '%s' to bb.debug", lvl)
+ mainlogger.warn("Passed invalid debug level '%s' to bb.debug", lvl)
args = (lvl,) + args
lvl = 1
- logger.debug(lvl, ''.join(args))
+ mainlogger.debug(lvl, ''.join(args))
def note(*args):
- logger.info(''.join(args))
+ mainlogger.info(''.join(args))
def warn(*args):
- logger.warn(''.join(args))
+ mainlogger.warn(''.join(args))
def error(*args, **kwargs):
- logger.error(''.join(args), extra=kwargs)
+ mainlogger.error(''.join(args), extra=kwargs)
def fatal(*args, **kwargs):
- logger.critical(''.join(args), extra=kwargs)
+ mainlogger.critical(''.join(args), extra=kwargs)
raise BBHandledException()
def deprecated(func, name=None, advice=""):
diff --git a/yocto-poky/bitbake/lib/bb/build.py b/yocto-poky/bitbake/lib/bb/build.py
index 22428a649..db5072cb4 100644
--- a/yocto-poky/bitbake/lib/bb/build.py
+++ b/yocto-poky/bitbake/lib/bb/build.py
@@ -156,7 +156,12 @@ class LogTee(object):
def flush(self):
self.outfile.flush()
-def exec_func(func, d, dirs = None):
+#
+# pythonexception allows the python exceptions generated to be raised
+# as the real exceptions (not FuncFailed) and without a backtrace at the
+# origin of the failure.
+#
+def exec_func(func, d, dirs = None, pythonexception=False):
"""Execute a BB 'function'"""
body = d.getVar(func, False)
@@ -224,22 +229,18 @@ def exec_func(func, d, dirs = None):
with bb.utils.fileslocked(lockfiles):
if ispython:
- exec_func_python(func, d, runfile, cwd=adir)
+ exec_func_python(func, d, runfile, cwd=adir, pythonexception=pythonexception)
else:
exec_func_shell(func, d, runfile, cwd=adir)
_functionfmt = """
-def {function}(d):
-{body}
-
{function}(d)
"""
logformatter = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
-def exec_func_python(func, d, runfile, cwd=None):
+def exec_func_python(func, d, runfile, cwd=None, pythonexception=False):
"""Execute a python BB 'function'"""
- bbfile = d.getVar('FILE', True)
- code = _functionfmt.format(function=func, body=d.getVar(func, True))
+ code = _functionfmt.format(function=func)
bb.utils.mkdirhier(os.path.dirname(runfile))
with open(runfile, 'w') as script:
bb.data.emit_func_python(func, script, d)
@@ -254,11 +255,18 @@ def exec_func_python(func, d, runfile, cwd=None):
bb.debug(2, "Executing python function %s" % func)
try:
- comp = utils.better_compile(code, func, bbfile)
- utils.better_exec(comp, {"d": d}, code, bbfile)
+ text = "def %s(d):\n%s" % (func, d.getVar(func, False))
+ fn = d.getVarFlag(func, "filename", False)
+ lineno = int(d.getVarFlag(func, "lineno", False))
+ bb.methodpool.insert_method(func, text, fn, lineno - 1)
+
+ comp = utils.better_compile(code, func, "exec_python_func() autogenerated")
+ utils.better_exec(comp, {"d": d}, code, "exec_python_func() autogenerated", pythonexception=pythonexception)
except (bb.parse.SkipRecipe, bb.build.FuncFailed):
raise
except:
+ if pythonexception:
+ raise
raise FuncFailed(func, None)
finally:
bb.debug(2, "Python function %s finished" % func)
@@ -277,9 +285,8 @@ bb_exit_handler() {
case $ret in
0) ;;
*) case $BASH_VERSION in
- "") echo "WARNING: exit code $ret from a shell command.";;
- *) echo "WARNING: ${BASH_SOURCE[0]}:${BASH_LINENO[0]} exit $ret from
- \"$BASH_COMMAND\"";;
+ "") echo "WARNING: exit code $ret from a shell command.";;
+ *) echo "WARNING: ${BASH_SOURCE[0]}:${BASH_LINENO[0]} exit $ret from '$BASH_COMMAND'";;
esac
exit $ret
esac
@@ -319,7 +326,7 @@ exit $ret
os.chmod(runfile, 0775)
cmd = runfile
- if d.getVarFlag(func, 'fakeroot'):
+ if d.getVarFlag(func, 'fakeroot', False):
fakerootcmd = d.getVar('FAKEROOT', True)
if fakerootcmd:
cmd = [fakerootcmd, runfile]
@@ -394,7 +401,7 @@ def _exec_task(fn, task, d, quieterr):
Execution of a task involves a bit more setup than executing a function,
running it with its own local metadata, and with some useful variables set.
"""
- if not d.getVarFlag(task, 'task'):
+ if not d.getVarFlag(task, 'task', False):
event.fire(TaskInvalid(task, d), d)
logger.error("No such task: %s" % task)
return 1
@@ -533,7 +540,7 @@ def _exec_task(fn, task, d, quieterr):
bb.utils.remove(loglink)
event.fire(TaskSucceeded(task, logfn, localdata), localdata)
- if not localdata.getVarFlag(task, 'nostamp') and not localdata.getVarFlag(task, 'selfstamp'):
+ if not localdata.getVarFlag(task, 'nostamp', False) and not localdata.getVarFlag(task, 'selfstamp', False):
make_stamp(task, localdata)
return 0
@@ -541,7 +548,7 @@ def _exec_task(fn, task, d, quieterr):
def exec_task(fn, task, d, profile = False):
try:
quieterr = False
- if d.getVarFlag(task, "quieterrors") is not None:
+ if d.getVarFlag(task, "quieterrors", False) is not None:
quieterr = True
if profile:
@@ -582,10 +589,10 @@ def stamp_internal(taskname, d, file_name, baseonly=False):
taskflagname = taskname.replace("_setscene", "")
if file_name:
- stamp = d.stamp_base[file_name].get(taskflagname) or d.stamp[file_name]
+ stamp = d.stamp[file_name]
extrainfo = d.stamp_extrainfo[file_name].get(taskflagname) or ""
else:
- stamp = d.getVarFlag(taskflagname, 'stamp-base', True) or d.getVar('STAMP', True)
+ stamp = d.getVar('STAMP', True)
file_name = d.getVar('BB_FILENAME', True)
extrainfo = d.getVarFlag(taskflagname, 'stamp-extra-info', True) or ""
@@ -616,10 +623,10 @@ def stamp_cleanmask_internal(taskname, d, file_name):
taskflagname = taskname.replace("_setscene", "")
if file_name:
- stamp = d.stamp_base_clean[file_name].get(taskflagname) or d.stampclean[file_name]
+ stamp = d.stampclean[file_name]
extrainfo = d.stamp_extrainfo[file_name].get(taskflagname) or ""
else:
- stamp = d.getVarFlag(taskflagname, 'stamp-base-clean', True) or d.getVar('STAMPCLEAN', True)
+ stamp = d.getVar('STAMPCLEAN', True)
file_name = d.getVar('BB_FILENAME', True)
extrainfo = d.getVarFlag(taskflagname, 'stamp-extra-info', True) or ""
@@ -746,7 +753,7 @@ def addtask(task, before, after, d):
bbtasks.append(task)
d.setVar('__BBTASKS', bbtasks)
- existing = d.getVarFlag(task, "deps") or []
+ existing = d.getVarFlag(task, "deps", False) or []
if after is not None:
# set up deps for function
for entry in after.split():
@@ -756,7 +763,7 @@ def addtask(task, before, after, d):
if before is not None:
# set up things that depend on this func
for entry in before.split():
- existing = d.getVarFlag(entry, "deps") or []
+ existing = d.getVarFlag(entry, "deps", False) or []
if task not in existing:
d.setVarFlag(entry, "deps", [task] + existing)
@@ -771,7 +778,7 @@ def deltask(task, d):
d.delVarFlag(task, 'deps')
for bbtask in d.getVar('__BBTASKS', False) or []:
- deps = d.getVarFlag(bbtask, 'deps') or []
+ deps = d.getVarFlag(bbtask, 'deps', False) or []
if task in deps:
deps.remove(task)
d.setVarFlag(bbtask, 'deps', deps)
diff --git a/yocto-poky/bitbake/lib/bb/cache.py b/yocto-poky/bitbake/lib/bb/cache.py
index ab09b08b5..af5b9fbc6 100644
--- a/yocto-poky/bitbake/lib/bb/cache.py
+++ b/yocto-poky/bitbake/lib/bb/cache.py
@@ -43,7 +43,7 @@ except ImportError:
logger.info("Importing cPickle failed. "
"Falling back to a very slow implementation.")
-__cache_version__ = "148"
+__cache_version__ = "149"
def getCacheFile(path, filename, data_hash):
return os.path.join(path, filename + "." + data_hash)
@@ -85,8 +85,8 @@ class RecipeInfoCommon(object):
return out_dict
@classmethod
- def getvar(cls, var, metadata):
- return metadata.getVar(var, True) or ''
+ def getvar(cls, var, metadata, expand = True):
+ return metadata.getVar(var, expand) or ''
class CoreRecipeInfo(RecipeInfoCommon):
@@ -99,7 +99,7 @@ class CoreRecipeInfo(RecipeInfoCommon):
self.timestamp = bb.parse.cached_mtime(filename)
self.variants = self.listvar('__VARIANTS', metadata) + ['']
self.appends = self.listvar('__BBAPPEND', metadata)
- self.nocache = self.getvar('__BB_DONT_CACHE', metadata)
+ self.nocache = self.getvar('BB_DONT_CACHE', metadata)
self.skipreason = self.getvar('__SKIPPED', metadata)
if self.skipreason:
@@ -129,8 +129,6 @@ class CoreRecipeInfo(RecipeInfoCommon):
self.not_world = self.getvar('EXCLUDE_FROM_WORLD', metadata)
self.stamp = self.getvar('STAMP', metadata)
self.stampclean = self.getvar('STAMPCLEAN', metadata)
- self.stamp_base = self.flaglist('stamp-base', self.tasks, metadata)
- self.stamp_base_clean = self.flaglist('stamp-base-clean', self.tasks, metadata)
self.stamp_extrainfo = self.flaglist('stamp-extra-info', self.tasks, metadata)
self.file_checksums = self.flaglist('file-checksums', self.tasks, metadata, True)
self.packages_dynamic = self.listvar('PACKAGES_DYNAMIC', metadata)
@@ -142,10 +140,11 @@ class CoreRecipeInfo(RecipeInfoCommon):
self.rprovides_pkg = self.pkgvar('RPROVIDES', self.packages, metadata)
self.rdepends_pkg = self.pkgvar('RDEPENDS', self.packages, metadata)
self.rrecommends_pkg = self.pkgvar('RRECOMMENDS', self.packages, metadata)
- self.inherits = self.getvar('__inherit_cache', metadata)
+ self.inherits = self.getvar('__inherit_cache', metadata, expand=False)
self.fakerootenv = self.getvar('FAKEROOTENV', metadata)
self.fakerootdirs = self.getvar('FAKEROOTDIRS', metadata)
self.fakerootnoenv = self.getvar('FAKEROOTNOENV', metadata)
+ self.extradepsfunc = self.getvar('calculate_extra_depends', metadata)
@classmethod
def init_cacheData(cls, cachedata):
@@ -158,8 +157,6 @@ class CoreRecipeInfo(RecipeInfoCommon):
cachedata.stamp = {}
cachedata.stampclean = {}
- cachedata.stamp_base = {}
- cachedata.stamp_base_clean = {}
cachedata.stamp_extrainfo = {}
cachedata.file_checksums = {}
cachedata.fn_provides = {}
@@ -183,6 +180,7 @@ class CoreRecipeInfo(RecipeInfoCommon):
cachedata.fakerootenv = {}
cachedata.fakerootnoenv = {}
cachedata.fakerootdirs = {}
+ cachedata.extradepsfunc = {}
def add_cacheData(self, cachedata, fn):
cachedata.task_deps[fn] = self.task_deps
@@ -192,8 +190,6 @@ class CoreRecipeInfo(RecipeInfoCommon):
cachedata.pkg_dp[fn] = self.defaultpref
cachedata.stamp[fn] = self.stamp
cachedata.stampclean[fn] = self.stampclean
- cachedata.stamp_base[fn] = self.stamp_base
- cachedata.stamp_base_clean[fn] = self.stamp_base_clean
cachedata.stamp_extrainfo[fn] = self.stamp_extrainfo
cachedata.file_checksums[fn] = self.file_checksums
@@ -220,7 +216,8 @@ class CoreRecipeInfo(RecipeInfoCommon):
rprovides += self.rprovides_pkg[package]
for rprovide in rprovides:
- cachedata.rproviders[rprovide].append(fn)
+ if fn not in cachedata.rproviders[rprovide]:
+ cachedata.rproviders[rprovide].append(fn)
for package in self.packages_dynamic:
cachedata.packages_dynamic[package].append(fn)
@@ -251,6 +248,7 @@ class CoreRecipeInfo(RecipeInfoCommon):
cachedata.fakerootenv[fn] = self.fakerootenv
cachedata.fakerootnoenv[fn] = self.fakerootnoenv
cachedata.fakerootdirs[fn] = self.fakerootdirs
+ cachedata.extradepsfunc[fn] = self.extradepsfunc
@@ -757,13 +755,14 @@ class MultiProcessCache(object):
self.cachedata = self.create_cachedata()
self.cachedata_extras = self.create_cachedata()
- def init_cache(self, d):
+ def init_cache(self, d, cache_file_name=None):
cachedir = (d.getVar("PERSISTENT_DIR", True) or
d.getVar("CACHE", True))
if cachedir in [None, '']:
return
bb.utils.mkdirhier(cachedir)
- self.cachefile = os.path.join(cachedir, self.__class__.cache_file_name)
+ self.cachefile = os.path.join(cachedir,
+ cache_file_name or self.__class__.cache_file_name)
logger.debug(1, "Using cache in '%s'", self.cachefile)
glf = bb.utils.lockfile(self.cachefile + ".lock")
@@ -787,7 +786,7 @@ class MultiProcessCache(object):
data = [{}]
return data
- def save_extras(self, d):
+ def save_extras(self):
if not self.cachefile:
return
@@ -817,7 +816,7 @@ class MultiProcessCache(object):
if h not in dest[j]:
dest[j][h] = source[j][h]
- def save_merge(self, d):
+ def save_merge(self):
if not self.cachefile:
return
diff --git a/yocto-poky/bitbake/lib/bb/checksum.py b/yocto-poky/bitbake/lib/bb/checksum.py
index 514ff0b1e..2ec964d73 100644
--- a/yocto-poky/bitbake/lib/bb/checksum.py
+++ b/yocto-poky/bitbake/lib/bb/checksum.py
@@ -15,6 +15,8 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+import glob
+import operator
import os
import stat
import bb.utils
@@ -88,3 +90,50 @@ class FileChecksumCache(MultiProcessCache):
dest[0][h] = source[0][h]
else:
dest[0][h] = source[0][h]
+
+ def get_checksums(self, filelist, pn):
+ """Get checksums for a list of files"""
+
+ def checksum_file(f):
+ try:
+ checksum = self.get_checksum(f)
+ except OSError as e:
+ bb.warn("Unable to get checksum for %s SRC_URI entry %s: %s" % (pn, os.path.basename(f), e))
+ return None
+ return checksum
+
+ def checksum_dir(pth):
+ # Handle directories recursively
+ dirchecksums = []
+ for root, dirs, files in os.walk(pth):
+ for name in files:
+ fullpth = os.path.join(root, name)
+ checksum = checksum_file(fullpth)
+ if checksum:
+ dirchecksums.append((fullpth, checksum))
+ return dirchecksums
+
+ checksums = []
+ for pth in filelist.split():
+ exist = pth.split(":")[1]
+ if exist == "False":
+ continue
+ pth = pth.split(":")[0]
+ if '*' in pth:
+ # Handle globs
+ for f in glob.glob(pth):
+ if os.path.isdir(f):
+ if not os.path.islink(f):
+ checksums.extend(checksum_dir(f))
+ else:
+ checksum = checksum_file(f)
+ checksums.append((f, checksum))
+ elif os.path.isdir(pth):
+ if not os.path.islink(pth):
+ checksums.extend(checksum_dir(pth))
+ else:
+ checksum = checksum_file(pth)
+ checksums.append((pth, checksum))
+
+ checksums.sort(key=operator.itemgetter(1))
+ return checksums
diff --git a/yocto-poky/bitbake/lib/bb/codeparser.py b/yocto-poky/bitbake/lib/bb/codeparser.py
index 82a3af4e0..3ee4d5622 100644
--- a/yocto-poky/bitbake/lib/bb/codeparser.py
+++ b/yocto-poky/bitbake/lib/bb/codeparser.py
@@ -28,6 +28,10 @@ def check_indent(codestr):
return codestr
if codestr[i-1] == "\t" or codestr[i-1] == " ":
+ if codestr[0] == "\n":
+ # Since we're adding a line, we need to remove one line of any empty padding
+ # to ensure line numbers are correct
+ codestr = codestr[1:]
return "if 1:\n" + codestr
return codestr
@@ -144,6 +148,10 @@ class CodeParserCache(MultiProcessCache):
return cacheline
def init_cache(self, d):
+ # Check if we already have the caches
+ if self.pythoncache:
+ return
+
MultiProcessCache.init_cache(self, d)
# cachedata gets re-assigned in the parent
@@ -159,11 +167,11 @@ codeparsercache = CodeParserCache()
def parser_cache_init(d):
codeparsercache.init_cache(d)
-def parser_cache_save(d):
- codeparsercache.save_extras(d)
+def parser_cache_save():
+ codeparsercache.save_extras()
-def parser_cache_savemerge(d):
- codeparsercache.save_merge(d)
+def parser_cache_savemerge():
+ codeparsercache.save_merge()
Logger = logging.getLoggerClass()
class BufferedLogger(Logger):
@@ -213,6 +221,17 @@ class PythonParser():
self.references.add(node.args[0].s)
else:
self.warn(node.func, node.args[0])
+ elif name and name.endswith(".expand"):
+ if isinstance(node.args[0], ast.Str):
+ value = node.args[0].s
+ d = bb.data.init()
+ parser = d.expandWithRefs(value, self.name)
+ self.references |= parser.references
+ self.execs |= parser.execs
+ for varname in parser.contains:
+ if varname not in self.contains:
+ self.contains[varname] = set()
+ self.contains[varname] |= parser.contains[varname]
elif name in self.execfuncs:
if isinstance(node.args[0], ast.Str):
self.var_execs.add(node.args[0].s)
@@ -235,6 +254,7 @@ class PythonParser():
break
def __init__(self, name, log):
+ self.name = name
self.var_execs = set()
self.contains = {}
self.execs = set()
@@ -244,7 +264,7 @@ class PythonParser():
self.unhandled_message = "in call of %s, argument '%s' is not a string literal"
self.unhandled_message = "while parsing %s, %s" % (name, self.unhandled_message)
- def parse_python(self, node):
+ def parse_python(self, node, lineno=0, filename="<string>"):
if not node or not node.strip():
return
@@ -266,7 +286,9 @@ class PythonParser():
self.contains[i] = set(codeparsercache.pythoncacheextras[h].contains[i])
return
- code = compile(check_indent(str(node)), "<string>", "exec",
+ # We can't add to the linenumbers for compile, we can pad to the correct number of blank lines though
+ node = "\n" * int(lineno) + node
+ code = compile(check_indent(str(node)), filename, "exec",
ast.PyCF_ONLY_AST)
for n in ast.walk(code):
diff --git a/yocto-poky/bitbake/lib/bb/command.py b/yocto-poky/bitbake/lib/bb/command.py
index 74106d143..0559ffc07 100644
--- a/yocto-poky/bitbake/lib/bb/command.py
+++ b/yocto-poky/bitbake/lib/bb/command.py
@@ -279,6 +279,7 @@ class CommandsSync:
mask = params[3]
return bb.event.set_UIHmask(handlerNum, llevel, debug_domains, mask)
setEventMask.needconfig = False
+ setEventMask.readonly = True
def setFeatures(self, command, params):
"""
diff --git a/yocto-poky/bitbake/lib/bb/cooker.py b/yocto-poky/bitbake/lib/bb/cooker.py
index 4df88818f..9b565fc37 100644
--- a/yocto-poky/bitbake/lib/bb/cooker.py
+++ b/yocto-poky/bitbake/lib/bb/cooker.py
@@ -67,6 +67,14 @@ class CollectionError(bb.BBHandledException):
class state:
initial, parsing, running, shutdown, forceshutdown, stopped, error = range(7)
+ @classmethod
+ def get_name(cls, code):
+ for name in dir(cls):
+ value = getattr(cls, name)
+ if type(value) == type(cls.initial) and value == code:
+ return name
+ raise ValueError("Invalid status code: %s" % code)
+
class SkippedPackage:
def __init__(self, info = None, reason = None):
@@ -136,6 +144,10 @@ class BBCooker:
self.watcher.bbwatchedfiles = []
self.notifier = pyinotify.Notifier(self.watcher, self.notifications)
+ # If being called by something like tinfoil, we need to clean cached data
+ # which may now be invalid
+ bb.parse.__mtime_cache = {}
+ bb.parse.BBHandler.cached_statements = {}
self.initConfigurationData()
@@ -189,13 +201,13 @@ class BBCooker:
def config_notifications(self, event):
if not event.pathname in self.configwatcher.bbwatchedfiles:
return
- if not event.path in self.inotify_modified_files:
- self.inotify_modified_files.append(event.path)
+ if not event.pathname in self.inotify_modified_files:
+ self.inotify_modified_files.append(event.pathname)
self.baseconfig_valid = False
def notifications(self, event):
- if not event.path in self.inotify_modified_files:
- self.inotify_modified_files.append(event.path)
+ if not event.pathname in self.inotify_modified_files:
+ self.inotify_modified_files.append(event.pathname)
self.parsecache_valid = False
def add_filewatch(self, deps, watcher=None):
@@ -234,9 +246,9 @@ class BBCooker:
def sigterm_exception(self, signum, stackframe):
if signum == signal.SIGTERM:
- bb.warn("Cooker recieved SIGTERM, shutting down...")
+ bb.warn("Cooker received SIGTERM, shutting down...")
elif signum == signal.SIGHUP:
- bb.warn("Cooker recieved SIGHUP, shutting down...")
+ bb.warn("Cooker received SIGHUP, shutting down...")
self.state = state.forceshutdown
def setFeatures(self, features):
@@ -645,7 +657,7 @@ class BBCooker:
data.expandKeys(envdata)
for e in envdata.keys():
if data.getVarFlag( e, 'python', envdata ):
- logger.plain("\npython %s () {\n%s}\n", e, envdata.getVar(e, True))
+ logger.plain("\npython %s () {\n%s}\n", e, envdata.getVar(e, False))
def buildTaskData(self, pkgs_to_build, task, abort, allowincomplete=False):
@@ -717,8 +729,15 @@ class BBCooker:
depend_tree["packages"] = {}
depend_tree["rdepends-pkg"] = {}
depend_tree["rrecs-pkg"] = {}
+ depend_tree['providermap'] = {}
depend_tree["layer-priorities"] = self.recipecache.bbfile_config_priorities
+ for name, fn in taskdata.get_providermap().iteritems():
+ pn = self.recipecache.pkg_fn[fn]
+ if name != pn:
+ version = "%s:%s-%s" % self.recipecache.pkg_pepvpr[fn]
+ depend_tree['providermap'][name] = (pn, version)
+
for task in xrange(len(rq.rqdata.runq_fnid)):
taskname = rq.rqdata.runq_task[task]
fnid = rq.rqdata.runq_fnid[task]
@@ -893,7 +912,7 @@ class BBCooker:
logger.info("PN build list saved to 'pn-buildlist'")
for pn in depgraph["depends"]:
for depend in depgraph["depends"][pn]:
- print('"%s" -> "%s"' % (pn, depend), file=depends_file)
+ print('"%s" -> "%s" [style=solid]' % (pn, depend), file=depends_file)
for pn in depgraph["rdepends-pn"]:
for rdepend in depgraph["rdepends-pn"][pn]:
print('"%s" -> "%s" [style=dashed]' % (pn, rdepend), file=depends_file)
@@ -911,13 +930,13 @@ class BBCooker:
else:
print('"%s" [label="%s(%s) %s\\n%s"]' % (package, package, pn, version, fn), file=depends_file)
for depend in depgraph["depends"][pn]:
- print('"%s" -> "%s"' % (package, depend), file=depends_file)
+ print('"%s" -> "%s" [style=solid]' % (package, depend), file=depends_file)
for package in depgraph["rdepends-pkg"]:
for rdepend in depgraph["rdepends-pkg"][package]:
print('"%s" -> "%s" [style=dashed]' % (package, rdepend), file=depends_file)
for package in depgraph["rrecs-pkg"]:
for rdepend in depgraph["rrecs-pkg"][package]:
- print('"%s" -> "%s" [style=dashed]' % (package, rdepend), file=depends_file)
+ print('"%s" -> "%s" [style=dotted]' % (package, rdepend), file=depends_file)
print("}", file=depends_file)
logger.info("Package dependencies saved to 'package-depends.dot'")
@@ -1019,22 +1038,21 @@ class BBCooker:
def findFilesMatchingInDir(self, filepattern, directory):
"""
- Searches for files matching the regex 'pattern' which are children of
+ Searches for files containing the substring 'filepattern' which are children of
'directory' in each BBPATH. i.e. to find all rootfs package classes available
to BitBake one could call findFilesMatchingInDir(self, 'rootfs_', 'classes')
or to find all machine configuration files one could call:
- findFilesMatchingInDir(self, 'conf/machines', 'conf')
+ findFilesMatchingInDir(self, '.conf', 'conf/machine')
"""
matches = []
- p = re.compile(re.escape(filepattern))
bbpaths = self.data.getVar('BBPATH', True).split(':')
for path in bbpaths:
dirpath = os.path.join(path, directory)
if os.path.exists(dirpath):
for root, dirs, files in os.walk(dirpath):
for f in files:
- if p.search(f):
+ if filepattern in f:
matches.append(f)
if matches:
@@ -1072,7 +1090,7 @@ class BBCooker:
for pfn in self.recipecache.pkg_fn:
inherits = self.recipecache.inherits.get(pfn, None)
- if inherits and inherits.count(klass) > 0:
+ if inherits and klass in inherits:
pkg_list.append(self.recipecache.pkg_fn[pfn])
return pkg_list
@@ -1095,28 +1113,6 @@ class BBCooker:
tree = self.generatePkgDepTreeData(pkgs, 'build')
bb.event.fire(bb.event.TargetsTreeGenerated(tree), self.data)
- def buildWorldTargetList(self):
- """
- Build package list for "bitbake world"
- """
- parselog.debug(1, "collating packages for \"world\"")
- for f in self.recipecache.possible_world:
- terminal = True
- pn = self.recipecache.pkg_fn[f]
-
- for p in self.recipecache.pn_provides[pn]:
- if p.startswith('virtual/'):
- parselog.debug(2, "World build skipping %s due to %s provider starting with virtual/", f, p)
- terminal = False
- break
- for pf in self.recipecache.providers[p]:
- if self.recipecache.pkg_fn[pf] != pn:
- parselog.debug(2, "World build skipping %s due to both us and %s providing %s", f, pf, p)
- terminal = False
- break
- if terminal:
- self.recipecache.world_target.add(pn)
-
def interactiveMode( self ):
"""Drop off into a shell"""
try:
@@ -1353,7 +1349,7 @@ class BBCooker:
failures += len(exc.args)
retval = False
except SystemExit as exc:
- self.command.finishAsyncCommand()
+ self.command.finishAsyncCommand(str(exc))
return False
if not retval:
@@ -1389,7 +1385,7 @@ class BBCooker:
failures += len(exc.args)
retval = False
except SystemExit as exc:
- self.command.finishAsyncCommand()
+ self.command.finishAsyncCommand(str(exc))
return False
if not retval:
@@ -1437,14 +1433,21 @@ class BBCooker:
dump = {}
for k in self.data.keys():
try:
- v = self.data.getVar(k, True)
+ expand = True
+ flags = self.data.getVarFlags(k)
+ if flags and "func" in flags and "python" in flags:
+ expand = False
+ v = self.data.getVar(k, expand)
if not k.startswith("__") and not isinstance(v, bb.data_smart.DataSmart):
dump[k] = {
'v' : v ,
'history' : self.data.varhistory.variable(k),
}
for d in flaglist:
- dump[k][d] = self.data.getVarFlag(k, d)
+ if flags and d in flags:
+ dump[k][d] = flags[d]
+ else:
+ dump[k][d] = None
except Exception as e:
print(e)
return dump
@@ -1506,6 +1509,8 @@ class BBCooker:
# reload files for which we got notifications
for p in self.inotify_modified_files:
bb.parse.update_cache(p)
+ if p in bb.parse.BBHandler.cached_statements:
+ del bb.parse.BBHandler.cached_statements[p]
self.inotify_modified_files = []
if not self.baseconfig_valid:
@@ -1577,7 +1582,7 @@ class BBCooker:
parselog.warn("Explicit target \"%s\" is in ASSUME_PROVIDED, ignoring" % pkg)
if 'world' in pkgs_to_build:
- self.buildWorldTargetList()
+ bb.providers.buildWorldTargetList(self.recipecache)
pkgs_to_build.remove('world')
for t in self.recipecache.world_target:
pkgs_to_build.append(t)
@@ -1643,6 +1648,9 @@ class BBCooker:
else:
self.state = state.shutdown
+ if self.parser:
+ self.parser.shutdown(clean=not force, force=force)
+
def finishcommand(self):
self.state = state.initial
@@ -1760,18 +1768,32 @@ class CookerCollectFiles(object):
globbed = glob.glob(f)
if not globbed and os.path.exists(f):
globbed = [f]
- for g in globbed:
+ # glob gives files in order on disk. Sort to be deterministic.
+ for g in sorted(globbed):
if g not in newfiles:
newfiles.append(g)
bbmask = config.getVar('BBMASK', True)
if bbmask:
+ # First validate the individual regular expressions and ignore any
+ # that do not compile
+ bbmasks = []
+ for mask in bbmask.split():
+ try:
+ re.compile(mask)
+ bbmasks.append(mask)
+ except sre_constants.error:
+ collectlog.critical("BBMASK contains an invalid regular expression, ignoring: %s" % mask)
+
+ # Then validate the combined regular expressions. This should never
+ # fail, but better safe than sorry...
+ bbmask = "|".join(bbmasks)
try:
bbmask_compiled = re.compile(bbmask)
except sre_constants.error:
- collectlog.critical("BBMASK is not a valid regular expression, ignoring.")
- return list(newfiles), 0
+ collectlog.critical("BBMASK is not a valid regular expression, ignoring: %s" % bbmask)
+ bbmask = None
bbfiles = []
bbappend = []
@@ -1948,9 +1970,17 @@ class Parser(multiprocessing.Process):
def parse(self, filename, appends, caches_array):
try:
+ # Record the filename we're parsing into any events generated
+ def parse_filter(self, record):
+ record.taskpid = bb.event.worker_pid
+ record.fn = filename
+ return True
+
# Reset our environment and handlers to the original settings
bb.utils.set_context(self.context.copy())
bb.event.set_class_handlers(self.handlers.copy())
+ bb.event.LogHandler.filter = parse_filter
+
return True, bb.cache.Cache.parse(filename, appends, self.cfg, caches_array)
except Exception as exc:
tb = sys.exc_info()[2]
@@ -1981,8 +2011,6 @@ class CookerParser(object):
self.total = len(filelist)
self.current = 0
- self.num_processes = int(self.cfgdata.getVar("BB_NUMBER_PARSE_THREADS", True) or
- multiprocessing.cpu_count())
self.process_names = []
self.bb_cache = bb.cache.Cache(self.cfgdata, self.cfghash, cooker.caches_array)
@@ -1997,6 +2025,9 @@ class CookerParser(object):
self.toparse = self.total - len(self.fromcache)
self.progress_chunk = max(self.toparse / 100, 1)
+ self.num_processes = min(int(self.cfgdata.getVar("BB_NUMBER_PARSE_THREADS", True) or
+ multiprocessing.cpu_count()), len(self.willparse))
+
self.start()
self.haveshutdown = False
@@ -2007,8 +2038,9 @@ class CookerParser(object):
bb.event.fire(bb.event.ParseStarted(self.toparse), self.cfgdata)
def init():
Parser.cfg = self.cfgdata
- multiprocessing.util.Finalize(None, bb.codeparser.parser_cache_save, args=(self.cfgdata,), exitpriority=1)
- multiprocessing.util.Finalize(None, bb.fetch.fetcher_parse_save, args=(self.cfgdata,), exitpriority=1)
+ bb.utils.set_process_name(multiprocessing.current_process().name)
+ multiprocessing.util.Finalize(None, bb.codeparser.parser_cache_save, exitpriority=1)
+ multiprocessing.util.Finalize(None, bb.fetch.fetcher_parse_save, exitpriority=1)
self.feeder_quit = multiprocessing.Queue(maxsize=1)
self.parser_quit = multiprocessing.Queue(maxsize=self.num_processes)
@@ -2040,7 +2072,7 @@ class CookerParser(object):
bb.event.fire(event, self.cfgdata)
self.feeder_quit.put(None)
for process in self.processes:
- self.jobs.put(None)
+ self.parser_quit.put(None)
else:
self.feeder_quit.put('cancel')
@@ -2061,8 +2093,8 @@ class CookerParser(object):
sync = threading.Thread(target=self.bb_cache.sync)
sync.start()
multiprocessing.util.Finalize(None, sync.join, exitpriority=-100)
- bb.codeparser.parser_cache_savemerge(self.cooker.data)
- bb.fetch.fetcher_parse_done(self.cooker.data)
+ bb.codeparser.parser_cache_savemerge()
+ bb.fetch.fetcher_parse_done()
if self.cooker.configuration.profile:
profiles = []
for i in self.process_names:
@@ -2125,11 +2157,6 @@ class CookerParser(object):
logger.error('ExpansionError during parsing %s: %s', value.recipe, str(exc))
self.shutdown(clean=False)
return False
- except SyntaxError as exc:
- self.error += 1
- logger.error('Unable to parse %s', exc.recipe)
- self.shutdown(clean=False)
- return False
except Exception as exc:
self.error += 1
etype, value, tb = sys.exc_info()
diff --git a/yocto-poky/bitbake/lib/bb/cookerdata.py b/yocto-poky/bitbake/lib/bb/cookerdata.py
index 671c0cb0e..50259a9a0 100644
--- a/yocto-poky/bitbake/lib/bb/cookerdata.py
+++ b/yocto-poky/bitbake/lib/bb/cookerdata.py
@@ -137,6 +137,7 @@ class CookerConfiguration(object):
self.force = False
self.profile = False
self.nosetscene = False
+ self.setsceneonly = False
self.invalidate_stamp = False
self.dump_signatures = []
self.dry_run = False
@@ -181,7 +182,7 @@ def catch_parse_error(func):
parselog.critical(traceback.format_exc())
parselog.critical("Unable to parse %s: %s" % (fn, exc))
sys.exit(1)
- except (bb.parse.ParseError, bb.data_smart.ExpansionError) as exc:
+ except bb.data_smart.ExpansionError as exc:
import traceback
bbdir = os.path.dirname(__file__) + os.sep
@@ -192,6 +193,8 @@ def catch_parse_error(func):
if not fn.startswith(bbdir):
break
parselog.critical("Unable to parse %s", fn, exc_info=(exc_class, exc, tb))
+ except bb.parse.ParseError as exc:
+ parselog.critical(str(exc))
sys.exit(1)
return wrapped
@@ -289,6 +292,8 @@ class CookerDataBuilder(object):
parselog.debug(2, "Adding layer %s", layer)
if 'HOME' in approved and '~' in layer:
layer = os.path.expanduser(layer)
+ if layer.endswith('/'):
+ layer = layer.rstrip('/')
data.setVar('LAYERDIR', layer)
data = parse_config_file(os.path.join(layer, "conf", "layer.conf"), data)
data.expandVarref('LAYERDIR')
@@ -317,7 +322,9 @@ class CookerDataBuilder(object):
# Nomally we only register event handlers at the end of parsing .bb files
# We register any handlers we've found so far here...
for var in data.getVar('__BBHANDLERS', False) or []:
- bb.event.register(var, data.getVar(var, False), (data.getVarFlag(var, "eventmask", True) or "").split())
+ handlerfn = data.getVarFlag(var, "filename", False)
+ handlerln = int(data.getVarFlag(var, "lineno", False))
+ bb.event.register(var, data.getVar(var, False), (data.getVarFlag(var, "eventmask", True) or "").split(), handlerfn, handlerln)
if data.getVar("BB_WORKERCONTEXT", False) is None:
bb.fetch.fetcher_init(data)
diff --git a/yocto-poky/bitbake/lib/bb/data.py b/yocto-poky/bitbake/lib/bb/data.py
index f6415a467..dbc6dea68 100644
--- a/yocto-poky/bitbake/lib/bb/data.py
+++ b/yocto-poky/bitbake/lib/bb/data.py
@@ -107,7 +107,7 @@ def setVarFlag(var, flag, flagvalue, d):
def getVarFlag(var, flag, d):
"""Gets given flag from given var"""
- return d.getVarFlag(var, flag)
+ return d.getVarFlag(var, flag, False)
def delVarFlag(var, flag, d):
"""Removes a given flag from the variable's flags"""
@@ -182,12 +182,12 @@ def inheritFromOS(d, savedenv, permitted):
def emit_var(var, o=sys.__stdout__, d = init(), all=False):
"""Emit a variable to be sourced by a shell."""
- if d.getVarFlag(var, "python"):
+ if d.getVarFlag(var, "python", False):
return False
- export = d.getVarFlag(var, "export")
- unexport = d.getVarFlag(var, "unexport")
- func = d.getVarFlag(var, "func")
+ export = d.getVarFlag(var, "export", False)
+ unexport = d.getVarFlag(var, "unexport", False)
+ func = d.getVarFlag(var, "func", False)
if not all and not export and not unexport and not func:
return False
@@ -227,6 +227,7 @@ def emit_var(var, o=sys.__stdout__, d = init(), all=False):
if func:
# NOTE: should probably check for unbalanced {} within the var
+ val = val.rstrip('\n')
o.write("%s() {\n%s\n}\n" % (varExpanded, val))
return 1
@@ -244,7 +245,7 @@ def emit_var(var, o=sys.__stdout__, d = init(), all=False):
def emit_env(o=sys.__stdout__, d = init(), all=False):
"""Emits all items in the data store in a format such that it can be sourced by a shell."""
- isfunc = lambda key: bool(d.getVarFlag(key, "func"))
+ isfunc = lambda key: bool(d.getVarFlag(key, "func", False))
keys = sorted((key for key in d.keys() if not key.startswith("__")), key=isfunc)
grouped = groupby(keys, isfunc)
for isfunc, keys in grouped:
@@ -253,8 +254,8 @@ def emit_env(o=sys.__stdout__, d = init(), all=False):
def exported_keys(d):
return (key for key in d.keys() if not key.startswith('__') and
- d.getVarFlag(key, 'export') and
- not d.getVarFlag(key, 'unexport'))
+ d.getVarFlag(key, 'export', False) and
+ not d.getVarFlag(key, 'unexport', False))
def exported_vars(d):
for key in exported_keys(d):
@@ -269,7 +270,7 @@ def exported_vars(d):
def emit_func(func, o=sys.__stdout__, d = init()):
"""Emits all items in the data store in a format such that it can be sourced by a shell."""
- keys = (key for key in d.keys() if not key.startswith("__") and not d.getVarFlag(key, "func"))
+ keys = (key for key in d.keys() if not key.startswith("__") and not d.getVarFlag(key, "func", False))
for key in keys:
emit_var(key, o, d, False)
@@ -283,7 +284,7 @@ def emit_func(func, o=sys.__stdout__, d = init()):
seen |= deps
newdeps = set()
for dep in deps:
- if d.getVarFlag(dep, "func") and not d.getVarFlag(dep, "python"):
+ if d.getVarFlag(dep, "func", False) and not d.getVarFlag(dep, "python", False):
emit_var(dep, o, d, False) and o.write('\n')
newdeps |= bb.codeparser.ShellParser(dep, logger).parse_shell(d.getVar(dep, True))
newdeps |= set((d.getVarFlag(dep, "vardeps", True) or "").split())
@@ -297,7 +298,7 @@ def emit_func_python(func, o=sys.__stdout__, d = init()):
"""Emits all items in the data store in a format such that it can be sourced by a shell."""
def write_func(func, o, call = False):
- body = d.getVar(func, True)
+ body = d.getVar(func, False)
if not body.startswith("def"):
body = _functionfmt.format(function=func, body=body)
@@ -307,7 +308,7 @@ def emit_func_python(func, o=sys.__stdout__, d = init()):
write_func(func, o, True)
pp = bb.codeparser.PythonParser(func, logger)
- pp.parse_python(d.getVar(func, True))
+ pp.parse_python(d.getVar(func, False))
newdeps = pp.execs
newdeps |= set((d.getVarFlag(func, "vardeps", True) or "").split())
seen = set()
@@ -316,10 +317,10 @@ def emit_func_python(func, o=sys.__stdout__, d = init()):
seen |= deps
newdeps = set()
for dep in deps:
- if d.getVarFlag(dep, "func") and d.getVarFlag(dep, "python"):
+ if d.getVarFlag(dep, "func", False) and d.getVarFlag(dep, "python", False):
write_func(dep, o)
pp = bb.codeparser.PythonParser(dep, logger)
- pp.parse_python(d.getVar(dep, True))
+ pp.parse_python(d.getVar(dep, False))
newdeps |= pp.execs
newdeps |= set((d.getVarFlag(dep, "vardeps", True) or "").split())
newdeps -= seen
@@ -338,7 +339,7 @@ def build_dependencies(key, keys, shelldeps, varflagsexcl, d):
deps |= parser.references
deps = deps | (keys & parser.execs)
return deps, value
- varflags = d.getVarFlags(key, ["vardeps", "vardepvalue", "vardepsexclude", "vardepvalueexclude", "postfuncs", "prefuncs"]) or {}
+ varflags = d.getVarFlags(key, ["vardeps", "vardepvalue", "vardepsexclude", "vardepvalueexclude", "postfuncs", "prefuncs", "lineno", "filename"]) or {}
vardeps = varflags.get("vardeps")
value = d.getVar(key, False)
@@ -361,27 +362,27 @@ def build_dependencies(key, keys, shelldeps, varflagsexcl, d):
value = varflags.get("vardepvalue")
elif varflags.get("func"):
if varflags.get("python"):
- parsedvar = d.expandWithRefs(value, key)
parser = bb.codeparser.PythonParser(key, logger)
- if parsedvar.value and "\t" in parsedvar.value:
+ if value and "\t" in value:
logger.warn("Variable %s contains tabs, please remove these (%s)" % (key, d.getVar("FILE", True)))
- parser.parse_python(parsedvar.value)
+ parser.parse_python(value, filename=varflags.get("filename"), lineno=varflags.get("lineno"))
deps = deps | parser.references
+ deps = deps | (keys & parser.execs)
value = handle_contains(value, parser.contains, d)
else:
parsedvar = d.expandWithRefs(value, key)
parser = bb.codeparser.ShellParser(key, logger)
parser.parse_shell(parsedvar.value)
deps = deps | shelldeps
+ deps = deps | parsedvar.references
+ deps = deps | (keys & parser.execs) | (keys & parsedvar.execs)
+ value = handle_contains(value, parsedvar.contains, d)
if vardeps is None:
parser.log.flush()
if "prefuncs" in varflags:
deps = deps | set(varflags["prefuncs"].split())
if "postfuncs" in varflags:
deps = deps | set(varflags["postfuncs"].split())
- deps = deps | parsedvar.references
- deps = deps | (keys & parser.execs) | (keys & parsedvar.execs)
- value = handle_contains(value, parsedvar.contains, d)
else:
parser = d.expandWithRefs(value, key)
deps |= parser.references
@@ -406,7 +407,8 @@ def build_dependencies(key, keys, shelldeps, varflagsexcl, d):
deps |= set((vardeps or "").split())
deps -= set(varflags.get("vardepsexclude", "").split())
except Exception as e:
- raise bb.data_smart.ExpansionError(key, None, e)
+ bb.warn("Exception during build_dependencies for %s" % key)
+ raise
return deps, value
#bb.note("Variable %s references %s and calls %s" % (key, str(deps), str(execs)))
#d.setVarFlag(key, "vardeps", deps)
@@ -414,7 +416,7 @@ def build_dependencies(key, keys, shelldeps, varflagsexcl, d):
def generate_dependencies(d):
keys = set(key for key in d if not key.startswith("__"))
- shelldeps = set(key for key in d.getVar("__exportlist", False) if d.getVarFlag(key, "export") and not d.getVarFlag(key, "unexport"))
+ shelldeps = set(key for key in d.getVar("__exportlist", False) if d.getVarFlag(key, "export", False) and not d.getVarFlag(key, "unexport", False))
varflagsexcl = d.getVar('BB_SIGNATURE_EXCLUDE_FLAGS', True)
deps = {}
diff --git a/yocto-poky/bitbake/lib/bb/data_smart.py b/yocto-poky/bitbake/lib/bb/data_smart.py
index 70558c15a..fa1e79427 100644
--- a/yocto-poky/bitbake/lib/bb/data_smart.py
+++ b/yocto-poky/bitbake/lib/bb/data_smart.py
@@ -40,7 +40,7 @@ logger = logging.getLogger("BitBake.Data")
__setvar_keyword__ = ["_append", "_prepend", "_remove"]
__setvar_regexp__ = re.compile('(?P<base>.*?)(?P<keyword>_append|_prepend|_remove)(_(?P<add>.*))?$')
-__expand_var_regexp__ = re.compile(r"\${[^{}@\n\t ]+}")
+__expand_var_regexp__ = re.compile(r"\${[^{}@\n\t :]+}")
__expand_python_regexp__ = re.compile(r"\${@.+?}")
def infer_caller_details(loginfo, parent = False, varval = True):
@@ -147,7 +147,7 @@ class DataContext(dict):
def __missing__(self, key):
value = self.metadata.getVar(key, True)
- if value is None or self.metadata.getVarFlag(key, 'func'):
+ if value is None or self.metadata.getVarFlag(key, 'func', False):
raise KeyError(key)
else:
return value
@@ -384,7 +384,12 @@ class DataSmart(MutableMapping):
olds = s
try:
s = __expand_var_regexp__.sub(varparse.var_sub, s)
- s = __expand_python_regexp__.sub(varparse.python_sub, s)
+ try:
+ s = __expand_python_regexp__.sub(varparse.python_sub, s)
+ except SyntaxError as e:
+ # Likely unmatched brackets, just don't expand the expression
+ if e.msg != "EOL while scanning string literal":
+ raise
if s == olds:
break
except ExpansionError:
@@ -475,7 +480,7 @@ class DataSmart(MutableMapping):
base = match.group('base')
keyword = match.group("keyword")
override = match.group('add')
- l = self.getVarFlag(base, keyword) or []
+ l = self.getVarFlag(base, keyword, False) or []
l.append([value, override])
self.setVarFlag(base, keyword, l, ignore=True)
# And cause that to be recorded:
@@ -547,7 +552,7 @@ class DataSmart(MutableMapping):
# aka pay the cookie monster
override = var[var.rfind('_')+1:]
shortvar = var[:var.rfind('_')]
- while override:
+ while override and override.islower():
if shortvar not in self.overridedata:
self.overridedata[shortvar] = []
if [var, override] not in self.overridedata[shortvar]:
@@ -561,7 +566,7 @@ class DataSmart(MutableMapping):
if len(shortvar) == 0:
override = None
- def getVar(self, var, expand=False, noweakdefault=False, parsing=False):
+ def getVar(self, var, expand, noweakdefault=False, parsing=False):
return self.getVarFlag(var, "_content", expand, noweakdefault, parsing)
def renameVar(self, key, newkey, **loginfo):
@@ -577,11 +582,11 @@ class DataSmart(MutableMapping):
self.setVar(newkey, val, ignore=True, parsing=True)
for i in (__setvar_keyword__):
- src = self.getVarFlag(key, i)
+ src = self.getVarFlag(key, i, False)
if src is None:
continue
- dest = self.getVarFlag(newkey, i) or []
+ dest = self.getVarFlag(newkey, i, False) or []
dest.extend(src)
self.setVarFlag(newkey, i, dest, ignore=True)
@@ -621,7 +626,7 @@ class DataSmart(MutableMapping):
if '_' in var:
override = var[var.rfind('_')+1:]
shortvar = var[:var.rfind('_')]
- while override:
+ while override and override.islower():
try:
if shortvar in self.overridedata:
# Force CoW by recreating the list first
@@ -658,7 +663,7 @@ class DataSmart(MutableMapping):
self.dict["__exportlist"]["_content"] = set()
self.dict["__exportlist"]["_content"].add(var)
- def getVarFlag(self, var, flag, expand=False, noweakdefault=False, parsing=False):
+ def getVarFlag(self, var, flag, expand, noweakdefault=False, parsing=False):
local_var = self._findVar(var)
value = None
if flag == "_content" and var in self.overridedata and not parsing:
@@ -687,7 +692,7 @@ class DataSmart(MutableMapping):
match = active[a]
del active[a]
if match:
- value = self.getVar(match)
+ value = self.getVar(match, False)
if local_var is not None and value is None:
if flag in local_var:
@@ -957,7 +962,7 @@ class DataSmart(MutableMapping):
if key == "__BBANONFUNCS":
for i in bb_list:
- value = d.getVar(i, True) or ""
+ value = d.getVar(i, False) or ""
data.update({i:value})
data_str = str([(k, data[k]) for k in sorted(data.keys())])
diff --git a/yocto-poky/bitbake/lib/bb/event.py b/yocto-poky/bitbake/lib/bb/event.py
index 366bc4188..5ffe89eae 100644
--- a/yocto-poky/bitbake/lib/bb/event.py
+++ b/yocto-poky/bitbake/lib/bb/event.py
@@ -31,6 +31,7 @@ except ImportError:
import logging
import atexit
import traceback
+import ast
import bb.utils
import bb.compat
import bb.exceptions
@@ -177,7 +178,7 @@ def fire_from_worker(event, d):
fire_ui_handlers(event, d)
noop = lambda _: None
-def register(name, handler, mask=None):
+def register(name, handler, mask=None, filename=None, lineno=None):
"""Register an Event handler"""
# already registered
@@ -189,7 +190,15 @@ def register(name, handler, mask=None):
if isinstance(handler, basestring):
tmp = "def %s(e):\n%s" % (name, handler)
try:
- code = compile(tmp, "%s(e)" % name, "exec")
+ code = bb.methodpool.compile_cache(tmp)
+ if not code:
+ if filename is None:
+ filename = "%s(e)" % name
+ code = compile(tmp, filename, "exec", ast.PyCF_ONLY_AST)
+ if lineno is not None:
+ ast.increment_lineno(code, lineno-1)
+ code = compile(code, filename, "exec")
+ bb.methodpool.compile_cache_add(tmp, code)
except SyntaxError:
logger.error("Unable to register event handler '%s':\n%s", name,
''.join(traceback.format_exc(limit=0)))
@@ -595,6 +604,8 @@ class LogHandler(logging.Handler):
etype, value, tb = record.exc_info
if hasattr(tb, 'tb_next'):
tb = list(bb.exceptions.extract_traceback(tb, context=3))
+ # Need to turn the value into something the logging system can pickle
+ value = str(value)
record.bb_exc_info = (etype, value, tb)
record.exc_info = None
fire(record, None)
diff --git a/yocto-poky/bitbake/lib/bb/fetch2/__init__.py b/yocto-poky/bitbake/lib/bb/fetch2/__init__.py
index a9c044b6a..1fa67020c 100644
--- a/yocto-poky/bitbake/lib/bb/fetch2/__init__.py
+++ b/yocto-poky/bitbake/lib/bb/fetch2/__init__.py
@@ -29,11 +29,9 @@ from __future__ import absolute_import
from __future__ import print_function
import os, re
import signal
-import glob
import logging
import urllib
import urlparse
-import operator
import bb.persist_data, bb.utils
import bb.checksum
from bb import data
@@ -329,7 +327,7 @@ class URI(object):
def path(self, path):
self._path = path
- if re.compile("^/").match(path):
+ if not path or re.compile("^/").match(path):
self.relative = False
else:
self.relative = True
@@ -377,9 +375,12 @@ def decodeurl(url):
if locidx != -1 and type.lower() != 'file':
host = location[:locidx]
path = location[locidx:]
- else:
+ elif type.lower() == 'file':
host = ""
path = location
+ else:
+ host = location
+ path = ""
if user:
m = re.compile('(?P<user>[^:]+)(:?(?P<pswd>.*))').match(user)
if m:
@@ -515,13 +516,13 @@ def fetcher_init(d):
if hasattr(m, "init"):
m.init(d)
-def fetcher_parse_save(d):
- _checksum_cache.save_extras(d)
+def fetcher_parse_save():
+ _checksum_cache.save_extras()
-def fetcher_parse_done(d):
- _checksum_cache.save_merge(d)
+def fetcher_parse_done():
+ _checksum_cache.save_merge()
-def fetcher_compare_revisions(d):
+def fetcher_compare_revisions():
"""
Compare the revisions in the persistant cache with current values and
return true/false on whether they've changed.
@@ -574,10 +575,10 @@ def verify_checksum(ud, d, precomputed={}):
else:
sha256data = bb.utils.sha256_file(ud.localpath)
- if ud.method.recommends_checksum(ud):
+ if ud.method.recommends_checksum(ud) and not ud.md5_expected and not ud.sha256_expected:
# If strict checking enabled and neither sum defined, raise error
strict = d.getVar("BB_STRICT_CHECKSUM", True) or "0"
- if (strict == "1") and not (ud.md5_expected or ud.sha256_expected):
+ if strict == "1":
logger.error('No checksum specified for %s, please add at least one to the recipe:\n'
'SRC_URI[%s] = "%s"\nSRC_URI[%s] = "%s"' %
(ud.localpath, ud.md5_name, md5data,
@@ -585,34 +586,22 @@ def verify_checksum(ud, d, precomputed={}):
raise NoChecksumError('Missing SRC_URI checksum', ud.url)
# Log missing sums so user can more easily add them
- if not ud.md5_expected:
- logger.warn('Missing md5 SRC_URI checksum for %s, consider adding to the recipe:\n'
- 'SRC_URI[%s] = "%s"',
- ud.localpath, ud.md5_name, md5data)
-
- if not ud.sha256_expected:
- logger.warn('Missing sha256 SRC_URI checksum for %s, consider adding to the recipe:\n'
- 'SRC_URI[%s] = "%s"',
- ud.localpath, ud.sha256_name, sha256data)
-
- md5mismatch = False
- sha256mismatch = False
-
- if ud.md5_expected != md5data:
- md5mismatch = True
-
- if ud.sha256_expected != sha256data:
- sha256mismatch = True
+ logger.warn('Missing md5 SRC_URI checksum for %s, consider adding to the recipe:\n'
+ 'SRC_URI[%s] = "%s"',
+ ud.localpath, ud.md5_name, md5data)
+ logger.warn('Missing sha256 SRC_URI checksum for %s, consider adding to the recipe:\n'
+ 'SRC_URI[%s] = "%s"',
+ ud.localpath, ud.sha256_name, sha256data)
# We want to alert the user if a checksum is defined in the recipe but
# it does not match.
msg = ""
mismatch = False
- if md5mismatch and ud.md5_expected:
+ if ud.md5_expected and ud.md5_expected != md5data:
msg = msg + "\nFile: '%s' has %s checksum %s when %s was expected" % (ud.localpath, 'md5', md5data, ud.md5_expected)
mismatch = True;
- if sha256mismatch and ud.sha256_expected:
+ if ud.sha256_expected and ud.sha256_expected != sha256data:
msg = msg + "\nFile: '%s' has %s checksum %s when %s was expected" % (ud.localpath, 'sha256', sha256data, ud.sha256_expected)
mismatch = True;
@@ -637,6 +626,9 @@ def verify_donestamp(ud, d, origud=None):
Returns True, if the donestamp exists and is valid, False otherwise. When
returning False, any existing done stamps are removed.
"""
+ if not ud.needdonestamp:
+ return True
+
if not os.path.exists(ud.donestamp):
return False
@@ -685,7 +677,8 @@ def verify_donestamp(ud, d, origud=None):
# incorrect stamp file.
logger.warn("Checksum mismatch for local file %s\n"
"Cleaning and trying again." % ud.localpath)
- rename_bad_checksum(ud, e.checksum)
+ if os.path.exists(ud.localpath):
+ rename_bad_checksum(ud, e.checksum)
bb.utils.remove(ud.donestamp)
return False
@@ -695,6 +688,9 @@ def update_stamp(ud, d):
donestamp is file stamp indicating the whole fetching is done
this function update the stamp after verifying the checksum
"""
+ if not ud.needdonestamp:
+ return
+
if os.path.exists(ud.donestamp):
# Touch the done stamp file to show active use of the download
try:
@@ -703,11 +699,21 @@ def update_stamp(ud, d):
# Errors aren't fatal here
pass
else:
- checksums = verify_checksum(ud, d)
- # Store the checksums for later re-verification against the recipe
- with open(ud.donestamp, "wb") as cachefile:
- p = pickle.Pickler(cachefile, pickle.HIGHEST_PROTOCOL)
- p.dump(checksums)
+ try:
+ checksums = verify_checksum(ud, d)
+ # Store the checksums for later re-verification against the recipe
+ with open(ud.donestamp, "wb") as cachefile:
+ p = pickle.Pickler(cachefile, pickle.HIGHEST_PROTOCOL)
+ p.dump(checksums)
+ except ChecksumError as e:
+ # Checksums failed to verify, trigger re-download and remove the
+ # incorrect stamp file.
+ logger.warn("Checksum mismatch for local file %s\n"
+ "Cleaning and trying again." % ud.localpath)
+ if os.path.exists(ud.localpath):
+ rename_bad_checksum(ud, e.checksum)
+ bb.utils.remove(ud.donestamp)
+ raise
def subprocess_setup():
# Python installs a SIGPIPE handler by default. This is usually not what
@@ -718,7 +724,7 @@ def subprocess_setup():
def get_autorev(d):
# only not cache src rev in autorev case
if d.getVar('BB_SRCREV_POLICY', True) != "cache":
- d.setVar('__BB_DONT_CACHE', '1')
+ d.setVar('BB_DONT_CACHE', '1')
return "AUTOINC"
def get_srcrev(d, method_name='sortable_revision'):
@@ -920,6 +926,10 @@ def rename_bad_checksum(ud, suffix):
def try_mirror_url(fetch, origud, ud, ld, check = False):
# Return of None or a value means we're finished
# False means try another url
+
+ if ud.lockfile and ud.lockfile != origud.lockfile:
+ lf = bb.utils.lockfile(ud.lockfile)
+
try:
if check:
found = ud.method.checkstatus(fetch, ud, ld)
@@ -946,8 +956,9 @@ def try_mirror_url(fetch, origud, ud, ld, check = False):
if origud.mirrortarball and os.path.basename(ud.localpath) == os.path.basename(origud.mirrortarball) \
and os.path.basename(ud.localpath) != os.path.basename(origud.localpath):
# Create donestamp in old format to avoid triggering a re-download
- bb.utils.mkdirhier(os.path.dirname(ud.donestamp))
- open(ud.donestamp, 'w').close()
+ if ud.donestamp:
+ bb.utils.mkdirhier(os.path.dirname(ud.donestamp))
+ open(ud.donestamp, 'w').close()
dest = os.path.join(dldir, os.path.basename(ud.localpath))
if not os.path.exists(dest):
os.symlink(ud.localpath, dest)
@@ -973,7 +984,8 @@ def try_mirror_url(fetch, origud, ud, ld, check = False):
if isinstance(e, ChecksumError):
logger.warn("Mirror checksum failure for url %s (original url: %s)\nCleaning and trying again." % (ud.url, origud.url))
logger.warn(str(e))
- rename_bad_checksum(ud, e.checksum)
+ if os.path.exists(ud.localpath):
+ rename_bad_checksum(ud, e.checksum)
elif isinstance(e, NoChecksumError):
raise
else:
@@ -984,6 +996,10 @@ def try_mirror_url(fetch, origud, ud, ld, check = False):
except UnboundLocalError:
pass
return False
+ finally:
+ if ud.lockfile and ud.lockfile != origud.lockfile:
+ bb.utils.unlockfile(lf)
+
def try_mirrors(fetch, d, origud, mirrors, check = False):
"""
@@ -1014,7 +1030,7 @@ def trusted_network(d, url):
return True
pkgname = d.expand(d.getVar('PN', False))
- trusted_hosts = d.getVarFlag('BB_ALLOWED_NETWORKS', pkgname)
+ trusted_hosts = d.getVarFlag('BB_ALLOWED_NETWORKS', pkgname, False)
if not trusted_hosts:
trusted_hosts = d.getVar('BB_ALLOWED_NETWORKS', True)
@@ -1028,6 +1044,7 @@ def trusted_network(d, url):
if not network:
return True
+ network = network.split(':')[0]
network = network.lower()
for host in trusted_hosts.split(" "):
@@ -1120,48 +1137,7 @@ def get_file_checksums(filelist, pn):
it proceeds
"""
-
- def checksum_file(f):
- try:
- checksum = _checksum_cache.get_checksum(f)
- except OSError as e:
- bb.warn("Unable to get checksum for %s SRC_URI entry %s: %s" % (pn, os.path.basename(f), e))
- return None
- return checksum
-
- def checksum_dir(pth):
- # Handle directories recursively
- dirchecksums = []
- for root, dirs, files in os.walk(pth):
- for name in files:
- fullpth = os.path.join(root, name)
- checksum = checksum_file(fullpth)
- if checksum:
- dirchecksums.append((fullpth, checksum))
- return dirchecksums
-
- checksums = []
- for pth in filelist.split():
- exist = pth.split(":")[1]
- if exist == "False":
- continue
- pth = pth.split(":")[0]
- if '*' in pth:
- # Handle globs
- for f in glob.glob(pth):
- if os.path.isdir(f):
- checksums.extend(checksum_dir(f))
- else:
- checksum = checksum_file(f)
- checksums.append((f, checksum))
- elif os.path.isdir(pth):
- checksums.extend(checksum_dir(pth))
- else:
- checksum = checksum_file(pth)
- checksums.append((pth, checksum))
-
- checksums.sort(key=operator.itemgetter(1))
- return checksums
+ return _checksum_cache.get_checksums(filelist, pn)
class FetchData(object):
@@ -1171,6 +1147,7 @@ class FetchData(object):
def __init__(self, url, d, localonly = False):
# localpath is the location of a downloaded result. If not set, the file is local.
self.donestamp = None
+ self.needdonestamp = True
self.localfile = ""
self.localpath = None
self.lockfile = None
@@ -1197,13 +1174,13 @@ class FetchData(object):
elif self.type not in ["http", "https", "ftp", "ftps", "sftp"]:
self.md5_expected = None
else:
- self.md5_expected = d.getVarFlag("SRC_URI", self.md5_name)
+ self.md5_expected = d.getVarFlag("SRC_URI", self.md5_name, True)
if self.sha256_name in self.parm:
self.sha256_expected = self.parm[self.sha256_name]
elif self.type not in ["http", "https", "ftp", "ftps", "sftp"]:
self.sha256_expected = None
else:
- self.sha256_expected = d.getVarFlag("SRC_URI", self.sha256_name)
+ self.sha256_expected = d.getVarFlag("SRC_URI", self.sha256_name, True)
self.ignore_checksums = False
self.names = self.parm.get("name",'default').split(',')
@@ -1235,13 +1212,20 @@ class FetchData(object):
self.localpath = self.method.localpath(self, d)
dldir = d.getVar("DL_DIR", True)
+
+ if not self.needdonestamp:
+ return
+
# Note: .done and .lock files should always be in DL_DIR whereas localpath may not be.
if self.localpath and self.localpath.startswith(dldir):
basepath = self.localpath
elif self.localpath:
basepath = dldir + os.sep + os.path.basename(self.localpath)
- else:
+ elif self.basepath or self.basename:
basepath = dldir + os.sep + (self.basepath or self.basename)
+ else:
+ bb.fatal("Can't determine lock path for url %s" % url)
+
self.donestamp = basepath + '.done'
self.lockfile = basepath + '.lock'
@@ -1355,6 +1339,11 @@ class FetchMethod(object):
iterate = False
file = urldata.localpath
+ # Localpath can't deal with 'dir/*' entries, so it converts them to '.',
+ # but it must be corrected back for local files copying
+ if urldata.basename == '*' and file.endswith('/.'):
+ file = '%s/%s' % (file.rstrip('/.'), urldata.path)
+
try:
unpack = bb.utils.to_boolean(urldata.parm.get('unpack'), True)
except ValueError as exc:
@@ -1407,51 +1396,40 @@ class FetchMethod(object):
cmd = 'rpm2cpio.sh %s | cpio -id' % (file)
elif file.endswith('.deb') or file.endswith('.ipk'):
cmd = 'ar -p %s data.tar.gz | zcat | tar --no-same-owner -xpf -' % file
+ elif file.endswith('.tar.7z'):
+ cmd = '7z x -so %s | tar xf - ' % file
+ elif file.endswith('.7z'):
+ cmd = '7za x -y %s 1>/dev/null' % file
+
+ # If 'subdir' param exists, create a dir and use it as destination for unpack cmd
+ if 'subdir' in urldata.parm:
+ unpackdir = '%s/%s' % (rootdir, urldata.parm.get('subdir'))
+ bb.utils.mkdirhier(unpackdir)
+ else:
+ unpackdir = rootdir
if not unpack or not cmd:
# If file == dest, then avoid any copies, as we already put the file into dest!
- dest = os.path.join(rootdir, os.path.basename(file))
- if (file != dest) and not (os.path.exists(dest) and os.path.samefile(file, dest)):
- if os.path.isdir(file):
- # If for example we're asked to copy file://foo/bar, we need to unpack the result into foo/bar
- basepath = getattr(urldata, "basepath", None)
- destdir = "."
- if basepath and basepath.endswith("/"):
- basepath = basepath.rstrip("/")
- elif basepath:
- basepath = os.path.dirname(basepath)
- if basepath and basepath.find("/") != -1:
- destdir = basepath[:basepath.rfind('/')]
- destdir = destdir.strip('/')
- if destdir != "." and not os.access("%s/%s" % (rootdir, destdir), os.F_OK):
- os.makedirs("%s/%s" % (rootdir, destdir))
- cmd = 'cp -fpPR %s %s/%s/' % (file, rootdir, destdir)
- #cmd = 'tar -cf - -C "%d" -ps . | tar -xf - -C "%s/%s/"' % (file, rootdir, destdir)
- else:
- # The "destdir" handling was specifically done for FILESPATH
- # items. So, only do so for file:// entries.
- if urldata.type == "file" and urldata.path.find("/") != -1:
- destdir = urldata.path.rsplit("/", 1)[0]
- if urldata.parm.get('subdir') != None:
- destdir = urldata.parm.get('subdir') + "/" + destdir
- else:
- if urldata.parm.get('subdir') != None:
- destdir = urldata.parm.get('subdir')
- else:
- destdir = "."
- bb.utils.mkdirhier("%s/%s" % (rootdir, destdir))
- cmd = 'cp -f %s %s/%s/' % (file, rootdir, destdir)
+ dest = os.path.join(unpackdir, os.path.basename(file))
+ if file != dest and not (os.path.exists(dest) and os.path.samefile(file, dest)):
+ destdir = '.'
+ # For file:// entries all intermediate dirs in path must be created at destination
+ if urldata.type == "file":
+ # Trailing '/' does a copying to wrong place
+ urlpath = urldata.path.rstrip('/')
+ # Want files places relative to cwd so no leading '/'
+ urlpath = urlpath.lstrip('/')
+ if urlpath.find("/") != -1:
+ destdir = urlpath.rsplit("/", 1)[0] + '/'
+ bb.utils.mkdirhier("%s/%s" % (unpackdir, destdir))
+ cmd = 'cp -fpPR %s %s' % (file, destdir)
if not cmd:
return
- # Change to subdir before executing command
+ # Change to unpackdir before executing command
save_cwd = os.getcwd();
- os.chdir(rootdir)
- if 'subdir' in urldata.parm:
- newdir = ("%s/%s" % (rootdir, urldata.parm.get('subdir')))
- bb.utils.mkdirhier(newdir)
- os.chdir(newdir)
+ os.chdir(unpackdir)
path = data.getVar('PATH', True)
if path:
@@ -1578,7 +1556,8 @@ class Fetch(object):
m = ud.method
localpath = ""
- lf = bb.utils.lockfile(ud.lockfile)
+ if ud.lockfile:
+ lf = bb.utils.lockfile(ud.lockfile)
try:
self.d.setVar("BB_NO_NETWORK", network)
@@ -1617,7 +1596,8 @@ class Fetch(object):
if isinstance(e, ChecksumError):
logger.warn("Checksum failure encountered with download of %s - will attempt other sources if available" % u)
logger.debug(1, str(e))
- rename_bad_checksum(ud, e.checksum)
+ if os.path.exists(ud.localpath):
+ rename_bad_checksum(ud, e.checksum)
elif isinstance(e, NoChecksumError):
raise
else:
@@ -1644,7 +1624,8 @@ class Fetch(object):
raise
finally:
- bb.utils.unlockfile(lf)
+ if ud.lockfile:
+ bb.utils.unlockfile(lf)
def checkstatus(self, urls=None):
"""
@@ -1686,9 +1667,6 @@ class Fetch(object):
ud = self.ud[u]
ud.setup_localpath(self.d)
- if self.d.expand(self.localpath) is None:
- continue
-
if ud.lockfile:
lf = bb.utils.lockfile(ud.lockfile)
@@ -1775,6 +1753,7 @@ from . import hg
from . import osc
from . import repo
from . import clearcase
+from . import npm
methods.append(local.Local())
methods.append(wget.Wget())
@@ -1791,3 +1770,4 @@ methods.append(hg.Hg())
methods.append(osc.Osc())
methods.append(repo.Repo())
methods.append(clearcase.ClearCase())
+methods.append(npm.Npm())
diff --git a/yocto-poky/bitbake/lib/bb/fetch2/git.py b/yocto-poky/bitbake/lib/bb/fetch2/git.py
index 9bd87ad25..526668bc2 100644
--- a/yocto-poky/bitbake/lib/bb/fetch2/git.py
+++ b/yocto-poky/bitbake/lib/bb/fetch2/git.py
@@ -70,6 +70,7 @@ import errno
import os
import re
import bb
+import errno
from bb import data
from bb.fetch2 import FetchMethod
from bb.fetch2 import runfetchcmd
@@ -261,23 +262,7 @@ class Git(FetchMethod):
if ud.bareclone:
cloneflags += " --mirror"
- # Versions of git prior to 1.7.9.2 have issues where foo.git and foo get confused
- # and you end up with some horrible union of the two when you attempt to clone it
- # The least invasive workaround seems to be a symlink to the real directory to
- # fool git into ignoring any .git version that may also be present.
- #
- # The issue is fixed in more recent versions of git so we can drop this hack in future
- # when that version becomes common enough.
- clonedir = ud.clonedir
- if not ud.path.endswith(".git"):
- indirectiondir = destdir[:-1] + ".indirectionsymlink"
- if os.path.exists(indirectiondir):
- os.remove(indirectiondir)
- bb.utils.mkdirhier(os.path.dirname(indirectiondir))
- os.symlink(ud.clonedir, indirectiondir)
- clonedir = indirectiondir
-
- runfetchcmd("%s clone %s %s/ %s" % (ud.basecmd, cloneflags, clonedir, destdir), d)
+ runfetchcmd("%s clone %s %s/ %s" % (ud.basecmd, cloneflags, ud.clonedir, destdir), d)
os.chdir(destdir)
repourl = self._get_repo_url(ud)
runfetchcmd("%s remote set-url origin %s" % (ud.basecmd, repourl), d)
@@ -379,7 +364,7 @@ class Git(FetchMethod):
"""
pupver = ('', '')
- tagregex = re.compile(d.getVar('GITTAGREGEX', True) or "(?P<pver>([0-9][\.|_]?)+)")
+ tagregex = re.compile(d.getVar('UPSTREAM_CHECK_GITTAGREGEX', True) or "(?P<pver>([0-9][\.|_]?)+)")
try:
output = self._lsremote(ud, d, "refs/tags/*")
except bb.fetch2.FetchError or bb.fetch2.NetworkAccess:
diff --git a/yocto-poky/bitbake/lib/bb/fetch2/gitsm.py b/yocto-poky/bitbake/lib/bb/fetch2/gitsm.py
index 0392e48d1..752f1d3c1 100644
--- a/yocto-poky/bitbake/lib/bb/fetch2/gitsm.py
+++ b/yocto-poky/bitbake/lib/bb/fetch2/gitsm.py
@@ -110,8 +110,7 @@ class GitSM(Git):
os.chdir(tmpclonedir)
runfetchcmd(ud.basecmd + " reset --hard", d)
runfetchcmd(ud.basecmd + " checkout " + ud.revisions[ud.names[0]], d)
- runfetchcmd(ud.basecmd + " submodule init", d)
- runfetchcmd(ud.basecmd + " submodule update", d)
+ runfetchcmd(ud.basecmd + " submodule update --init --recursive", d)
self._set_relative_paths(tmpclonedir)
runfetchcmd("sed " + gitdir + "/config -i -e 's/bare.*=.*false/bare = true/'", d)
os.rename(gitdir, ud.clonedir,)
@@ -131,7 +130,5 @@ class GitSM(Git):
os.chdir(ud.destdir)
submodules = self.uses_submodules(ud, d)
if submodules:
- runfetchcmd("cp -r " + ud.clonedir + "/modules " + ud.destdir + "/.git/", d)
- runfetchcmd(ud.basecmd + " submodule init", d)
- runfetchcmd(ud.basecmd + " submodule update", d)
-
+ runfetchcmd(ud.basecmd + " checkout " + ud.revisions[ud.names[0]], d)
+ runfetchcmd(ud.basecmd + " submodule update --init --recursive", d)
diff --git a/yocto-poky/bitbake/lib/bb/fetch2/local.py b/yocto-poky/bitbake/lib/bb/fetch2/local.py
index 2d921f7e5..303a52b63 100644
--- a/yocto-poky/bitbake/lib/bb/fetch2/local.py
+++ b/yocto-poky/bitbake/lib/bb/fetch2/local.py
@@ -45,6 +45,7 @@ class Local(FetchMethod):
ud.decodedurl = urllib.unquote(ud.url.split("://")[1].split(";")[0])
ud.basename = os.path.basename(ud.decodedurl)
ud.basepath = ud.decodedurl
+ ud.needdonestamp = False
return
def localpath(self, urldata, d):
diff --git a/yocto-poky/bitbake/lib/bb/fetch2/npm.py b/yocto-poky/bitbake/lib/bb/fetch2/npm.py
new file mode 100644
index 000000000..e8d9b1109
--- /dev/null
+++ b/yocto-poky/bitbake/lib/bb/fetch2/npm.py
@@ -0,0 +1,284 @@
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+"""
+BitBake 'Fetch' NPM implementation
+
+The NPM fetcher is used to retrieve files from the npmjs repository
+
+Usage in the recipe:
+
+ SRC_URI = "npm://registry.npmjs.org/;name=${PN};version=${PV}"
+ Suported SRC_URI options are:
+
+ - name
+ - version
+
+ npm://registry.npmjs.org/${PN}/-/${PN}-${PV}.tgz would become npm://registry.npmjs.org;name=${PN};ver=${PV}
+ The fetcher all triggers off the existence of ud.localpath. If that exists and has the ".done" stamp, its assumed the fetch is good/done
+
+"""
+
+import os
+import sys
+import urllib
+import json
+import subprocess
+import signal
+import bb
+from bb import data
+from bb.fetch2 import FetchMethod
+from bb.fetch2 import FetchError
+from bb.fetch2 import ChecksumError
+from bb.fetch2 import runfetchcmd
+from bb.fetch2 import logger
+from bb.fetch2 import UnpackError
+from bb.fetch2 import ParameterError
+from distutils import spawn
+
+def subprocess_setup():
+ # Python installs a SIGPIPE handler by default. This is usually not what
+ # non-Python subprocesses expect.
+ # SIGPIPE errors are known issues with gzip/bash
+ signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+
+class Npm(FetchMethod):
+
+ """Class to fetch urls via 'npm'"""
+ def init(self, d):
+ pass
+
+ def supports(self, ud, d):
+ """
+ Check to see if a given url can be fetched with npm
+ """
+ return ud.type in ['npm']
+
+ def debug(self, msg):
+ logger.debug(1, "NpmFetch: %s", msg)
+
+ def clean(self, ud, d):
+ logger.debug(2, "Calling cleanup %s" % ud.pkgname)
+ bb.utils.remove(ud.localpath, False)
+ bb.utils.remove(ud.pkgdatadir, True)
+ bb.utils.remove(ud.fullmirror, False)
+
+ def urldata_init(self, ud, d):
+ """
+ init NPM specific variable within url data
+ """
+ if 'downloadfilename' in ud.parm:
+ ud.basename = ud.parm['downloadfilename']
+ else:
+ ud.basename = os.path.basename(ud.path)
+
+ # can't call it ud.name otherwise fetcher base class will start doing sha1stuff
+ # TODO: find a way to get an sha1/sha256 manifest of pkg & all deps
+ ud.pkgname = ud.parm.get("name", None)
+ if not ud.pkgname:
+ raise ParameterError("NPM fetcher requires a name parameter", ud.url)
+ ud.version = ud.parm.get("version", None)
+ if not ud.version:
+ raise ParameterError("NPM fetcher requires a version parameter", ud.url)
+ ud.bbnpmmanifest = "%s-%s.deps.json" % (ud.pkgname, ud.version)
+ ud.registry = "http://%s" % (ud.url.replace('npm://', '', 1).split(';'))[0]
+ prefixdir = "npm/%s" % ud.pkgname
+ ud.pkgdatadir = d.expand("${DL_DIR}/%s" % prefixdir)
+ if not os.path.exists(ud.pkgdatadir):
+ bb.utils.mkdirhier(ud.pkgdatadir)
+ ud.localpath = d.expand("${DL_DIR}/npm/%s" % ud.bbnpmmanifest)
+
+ self.basecmd = d.getVar("FETCHCMD_wget", True) or "/usr/bin/env wget -O -t 2 -T 30 -nv --passive-ftp --no-check-certificate "
+ self.basecmd += " --directory-prefix=%s " % prefixdir
+
+ ud.write_tarballs = ((data.getVar("BB_GENERATE_MIRROR_TARBALLS", d, True) or "0") != "0")
+ ud.mirrortarball = 'npm_%s-%s.tar.xz' % (ud.pkgname, ud.version)
+ ud.fullmirror = os.path.join(d.getVar("DL_DIR", True), ud.mirrortarball)
+
+ def need_update(self, ud, d):
+ if os.path.exists(ud.localpath):
+ return False
+ return True
+
+ def _runwget(self, ud, d, command, quiet):
+ logger.debug(2, "Fetching %s using command '%s'" % (ud.url, command))
+ bb.fetch2.check_network_access(d, command)
+ runfetchcmd(command, d, quiet)
+
+ def _unpackdep(self, ud, pkg, data, destdir, dldir, d):
+ file = data[pkg]['tgz']
+ logger.debug(2, "file to extract is %s" % file)
+ if file.endswith('.tgz') or file.endswith('.tar.gz') or file.endswith('.tar.Z'):
+ cmd = 'tar xz --strip 1 --no-same-owner --warning=no-unknown-keyword -f %s/%s' % (dldir, file)
+ else:
+ bb.fatal("NPM package %s downloaded not a tarball!" % file)
+
+ # Change to subdir before executing command
+ save_cwd = os.getcwd()
+ if not os.path.exists(destdir):
+ os.makedirs(destdir)
+ os.chdir(destdir)
+ path = d.getVar('PATH', True)
+ if path:
+ cmd = "PATH=\"%s\" %s" % (path, cmd)
+ bb.note("Unpacking %s to %s/" % (file, os.getcwd()))
+ ret = subprocess.call(cmd, preexec_fn=subprocess_setup, shell=True)
+ os.chdir(save_cwd)
+
+ if ret != 0:
+ raise UnpackError("Unpack command %s failed with return value %s" % (cmd, ret), ud.url)
+
+ if 'deps' not in data[pkg]:
+ return
+ for dep in data[pkg]['deps']:
+ self._unpackdep(ud, dep, data[pkg]['deps'], "%s/node_modules/%s" % (destdir, dep), dldir, d)
+
+
+ def unpack(self, ud, destdir, d):
+ dldir = d.getVar("DL_DIR", True)
+ depdumpfile = "%s-%s.deps.json" % (ud.pkgname, ud.version)
+ with open("%s/npm/%s" % (dldir, depdumpfile)) as datafile:
+ workobj = json.load(datafile)
+ dldir = "%s/%s" % (os.path.dirname(ud.localpath), ud.pkgname)
+
+ self._unpackdep(ud, ud.pkgname, workobj, "%s/npmpkg" % destdir, dldir, d)
+
+ def _parse_view(self, output):
+ '''
+ Parse the output of npm view --json; the last JSON result
+ is assumed to be the one that we're interested in.
+ '''
+ pdata = None
+ outdeps = {}
+ datalines = []
+ bracelevel = 0
+ for line in output.splitlines():
+ if bracelevel:
+ datalines.append(line)
+ elif '{' in line:
+ datalines = []
+ datalines.append(line)
+ bracelevel = bracelevel + line.count('{') - line.count('}')
+ if datalines:
+ pdata = json.loads('\n'.join(datalines))
+ return pdata
+
+ def _getdependencies(self, pkg, data, version, d, ud, optional=False):
+ pkgfullname = pkg
+ if version != '*' and not '/' in version:
+ pkgfullname += "@'%s'" % version
+ logger.debug(2, "Calling getdeps on %s" % pkg)
+ fetchcmd = "npm view %s --json --registry %s" % (pkgfullname, ud.registry)
+ output = runfetchcmd(fetchcmd, d, True)
+ pdata = self._parse_view(output)
+ if not pdata:
+ raise FetchError("The command '%s' returned no output" % fetchcmd)
+ if optional:
+ pkg_os = pdata.get('os', None)
+ if pkg_os:
+ if not isinstance(pkg_os, list):
+ pkg_os = [pkg_os]
+ if 'linux' not in pkg_os or '!linux' in pkg_os:
+ logger.debug(2, "Skipping %s since it's incompatible with Linux" % pkg)
+ return
+ #logger.debug(2, "Output URL is %s - %s - %s" % (ud.basepath, ud.basename, ud.localfile))
+ outputurl = pdata['dist']['tarball']
+ data[pkg] = {}
+ data[pkg]['tgz'] = os.path.basename(outputurl)
+ self._runwget(ud, d, "%s %s" % (self.basecmd, outputurl), False)
+
+ dependencies = pdata.get('dependencies', {})
+ optionalDependencies = pdata.get('optionalDependencies', {})
+ depsfound = {}
+ optdepsfound = {}
+ data[pkg]['deps'] = {}
+ for dep in dependencies:
+ if dep in optionalDependencies:
+ optdepsfound[dep] = dependencies[dep]
+ else:
+ depsfound[dep] = dependencies[dep]
+ for dep, version in optdepsfound.iteritems():
+ self._getdependencies(dep, data[pkg]['deps'], version, d, ud, optional=True)
+ for dep, version in depsfound.iteritems():
+ self._getdependencies(dep, data[pkg]['deps'], version, d, ud)
+
+ def _getshrinkeddependencies(self, pkg, data, version, d, ud, lockdown, manifest):
+ logger.debug(2, "NPM shrinkwrap file is %s" % data)
+ outputurl = "invalid"
+ if ('resolved' not in data) or (not data['resolved'].startswith('http')):
+ # will be the case for ${PN}
+ fetchcmd = "npm view %s@%s dist.tarball --registry %s" % (pkg, version, ud.registry)
+ logger.debug(2, "Found this matching URL: %s" % str(fetchcmd))
+ outputurl = runfetchcmd(fetchcmd, d, True)
+ else:
+ outputurl = data['resolved']
+ self._runwget(ud, d, "%s %s" % (self.basecmd, outputurl), False)
+ manifest[pkg] = {}
+ manifest[pkg]['tgz'] = os.path.basename(outputurl).rstrip()
+ manifest[pkg]['deps'] = {}
+
+ if pkg in lockdown:
+ sha1_expected = lockdown[pkg][version]
+ sha1_data = bb.utils.sha1_file("npm/%s/%s" % (ud.pkgname, manifest[pkg]['tgz']))
+ if sha1_expected != sha1_data:
+ msg = "\nFile: '%s' has %s checksum %s when %s was expected" % (manifest[pkg]['tgz'], 'sha1', sha1_data, sha1_expected)
+ raise ChecksumError('Checksum mismatch!%s' % msg)
+ else:
+ logger.debug(2, "No lockdown data for %s@%s" % (pkg, version))
+
+ if 'dependencies' in data:
+ for obj in data['dependencies']:
+ logger.debug(2, "Found dep is %s" % str(obj))
+ self._getshrinkeddependencies(obj, data['dependencies'][obj], data['dependencies'][obj]['version'], d, ud, lockdown, manifest[pkg]['deps'])
+
+ def download(self, ud, d):
+ """Fetch url"""
+ jsondepobj = {}
+ shrinkobj = {}
+ lockdown = {}
+
+ if not os.listdir(ud.pkgdatadir) and os.path.exists(ud.fullmirror):
+ dest = d.getVar("DL_DIR", True)
+ bb.utils.mkdirhier(dest)
+ save_cwd = os.getcwd()
+ os.chdir(dest)
+ runfetchcmd("tar -xJf %s" % (ud.fullmirror), d)
+ os.chdir(save_cwd)
+ return
+
+ shwrf = d.getVar('NPM_SHRINKWRAP', True)
+ logger.debug(2, "NPM shrinkwrap file is %s" % shwrf)
+ try:
+ with open(shwrf) as datafile:
+ shrinkobj = json.load(datafile)
+ except:
+ logger.warn('Missing shrinkwrap file in NPM_SHRINKWRAP for %s, this will lead to unreliable builds!' % ud.pkgname)
+ lckdf = d.getVar('NPM_LOCKDOWN', True)
+ logger.debug(2, "NPM lockdown file is %s" % lckdf)
+ try:
+ with open(lckdf) as datafile:
+ lockdown = json.load(datafile)
+ except:
+ logger.warn('Missing lockdown file in NPM_LOCKDOWN for %s, this will lead to unreproducible builds!' % ud.pkgname)
+
+ if ('name' not in shrinkobj):
+ self._getdependencies(ud.pkgname, jsondepobj, ud.version, d, ud)
+ else:
+ self._getshrinkeddependencies(ud.pkgname, shrinkobj, ud.version, d, ud, lockdown, jsondepobj)
+
+ with open(ud.localpath, 'w') as outfile:
+ json.dump(jsondepobj, outfile)
+
+ def build_mirror_data(self, ud, d):
+ # Generate a mirror tarball if needed
+ if ud.write_tarballs and not os.path.exists(ud.fullmirror):
+ # it's possible that this symlink points to read-only filesystem with PREMIRROR
+ if os.path.islink(ud.fullmirror):
+ os.unlink(ud.fullmirror)
+
+ save_cwd = os.getcwd()
+ os.chdir(d.getVar("DL_DIR", True))
+ logger.info("Creating tarball of npm data")
+ runfetchcmd("tar -cJf %s npm/%s npm/%s" % (ud.fullmirror, ud.bbnpmmanifest, ud.pkgname), d)
+ runfetchcmd("touch %s.done" % (ud.fullmirror), d)
+ os.chdir(save_cwd)
+
diff --git a/yocto-poky/bitbake/lib/bb/fetch2/osc.py b/yocto-poky/bitbake/lib/bb/fetch2/osc.py
index 3d8779682..d051dfdaf 100644
--- a/yocto-poky/bitbake/lib/bb/fetch2/osc.py
+++ b/yocto-poky/bitbake/lib/bb/fetch2/osc.py
@@ -34,13 +34,13 @@ class Osc(FetchMethod):
# Create paths to osc checkouts
relpath = self._strip_leading_slashes(ud.path)
- ud.pkgdir = os.path.join(data.expand('${OSCDIR}', d), ud.host)
+ ud.pkgdir = os.path.join(d.getVar('OSCDIR', True), ud.host)
ud.moddir = os.path.join(ud.pkgdir, relpath, ud.module)
if 'rev' in ud.parm:
ud.revision = ud.parm['rev']
else:
- pv = data.getVar("PV", d, 0)
+ pv = d.getVar("PV", False)
rev = bb.fetch2.srcrev_internal_helper(ud, d)
if rev and rev != True:
ud.revision = rev
@@ -84,7 +84,7 @@ class Osc(FetchMethod):
logger.debug(2, "Fetch: checking for module directory '" + ud.moddir + "'")
- if os.access(os.path.join(data.expand('${OSCDIR}', d), ud.path, ud.module), os.R_OK):
+ if os.access(os.path.join(d.getVar('OSCDIR', True), ud.path, ud.module), os.R_OK):
oscupdatecmd = self._buildosccommand(ud, d, "update")
logger.info("Update "+ ud.url)
# update sources there
@@ -114,7 +114,7 @@ class Osc(FetchMethod):
Generate a .oscrc to be used for this run.
"""
- config_path = os.path.join(data.expand('${OSCDIR}', d), "oscrc")
+ config_path = os.path.join(d.getVar('OSCDIR', True), "oscrc")
if (os.path.exists(config_path)):
os.remove(config_path)
@@ -123,8 +123,8 @@ class Osc(FetchMethod):
f.write("apisrv = %s\n" % ud.host)
f.write("scheme = http\n")
f.write("su-wrapper = su -c\n")
- f.write("build-root = %s\n" % data.expand('${WORKDIR}', d))
- f.write("urllist = http://moblin-obs.jf.intel.com:8888/build/%(project)s/%(repository)s/%(buildarch)s/:full/%(name)s.rpm\n")
+ f.write("build-root = %s\n" % d.getVar('WORKDIR', True))
+ f.write("urllist = %s\n" % d.getVar("OSCURLLIST", True))
f.write("extra-pkgs = gzip\n")
f.write("\n")
f.write("[%s]\n" % ud.host)
diff --git a/yocto-poky/bitbake/lib/bb/fetch2/wget.py b/yocto-poky/bitbake/lib/bb/fetch2/wget.py
index bd2a8972a..8bc9e93ca 100644
--- a/yocto-poky/bitbake/lib/bb/fetch2/wget.py
+++ b/yocto-poky/bitbake/lib/bb/fetch2/wget.py
@@ -37,7 +37,9 @@ from bb.fetch2 import FetchMethod
from bb.fetch2 import FetchError
from bb.fetch2 import logger
from bb.fetch2 import runfetchcmd
+from bb.utils import export_proxies
from bs4 import BeautifulSoup
+from bs4 import SoupStrainer
class Wget(FetchMethod):
"""Class to fetch urls via 'wget'"""
@@ -61,6 +63,8 @@ class Wget(FetchMethod):
ud.basename = os.path.basename(ud.path)
ud.localfile = data.expand(urllib.unquote(ud.basename), d)
+ if not ud.localfile:
+ ud.localfile = data.expand(urllib.unquote(ud.host + ud.path).replace("/", "."), d)
self.basecmd = d.getVar("FETCHCMD_wget", True) or "/usr/bin/env wget -t 2 -T 30 -nv --passive-ftp --no-check-certificate"
@@ -218,54 +222,64 @@ class Wget(FetchMethod):
return resp
- def export_proxies(d):
- variables = ['http_proxy', 'HTTP_PROXY', 'https_proxy', 'HTTPS_PROXY',
- 'ftp_proxy', 'FTP_PROXY', 'no_proxy', 'NO_PROXY']
- exported = False
-
- for v in variables:
- if v in os.environ.keys():
- exported = True
- else:
- v_proxy = d.getVar(v, True)
- if v_proxy is not None:
- os.environ[v] = v_proxy
- exported = True
-
- return exported
-
- def head_method(self):
- return "HEAD"
-
+ class HTTPMethodFallback(urllib2.BaseHandler):
+ """
+ Fallback to GET if HEAD is not allowed (405 HTTP error)
+ """
+ def http_error_405(self, req, fp, code, msg, headers):
+ fp.read()
+ fp.close()
+
+ newheaders = dict((k,v) for k,v in req.headers.items()
+ if k.lower() not in ("content-length", "content-type"))
+ return self.parent.open(urllib2.Request(req.get_full_url(),
+ headers=newheaders,
+ origin_req_host=req.get_origin_req_host(),
+ unverifiable=True))
+
+ """
+ Some servers (e.g. GitHub archives, hosted on Amazon S3) return 403
+ Forbidden when they actually mean 405 Method Not Allowed.
+ """
+ http_error_403 = http_error_405
+
+ """
+ Some servers (e.g. FusionForge) returns 406 Not Acceptable when they
+ actually mean 405 Method Not Allowed.
+ """
+ http_error_406 = http_error_405
+
+ class FixedHTTPRedirectHandler(urllib2.HTTPRedirectHandler):
+ """
+ urllib2.HTTPRedirectHandler resets the method to GET on redirect,
+ when we want to follow redirects using the original method.
+ """
+ def redirect_request(self, req, fp, code, msg, headers, newurl):
+ newreq = urllib2.HTTPRedirectHandler.redirect_request(self, req, fp, code, msg, headers, newurl)
+ newreq.get_method = lambda: req.get_method()
+ return newreq
exported_proxies = export_proxies(d)
+ handlers = [FixedHTTPRedirectHandler, HTTPMethodFallback]
+ if export_proxies:
+ handlers.append(urllib2.ProxyHandler())
+ handlers.append(CacheHTTPHandler())
# XXX: Since Python 2.7.9 ssl cert validation is enabled by default
# see PEP-0476, this causes verification errors on some https servers
# so disable by default.
import ssl
- ssl_context = None
if hasattr(ssl, '_create_unverified_context'):
- ssl_context = ssl._create_unverified_context()
-
- if exported_proxies == True and ssl_context is not None:
- opener = urllib2.build_opener(urllib2.ProxyHandler, CacheHTTPHandler,
- urllib2.HTTPSHandler(context=ssl_context))
- elif exported_proxies == False and ssl_context is not None:
- opener = urllib2.build_opener(CacheHTTPHandler,
- urllib2.HTTPSHandler(context=ssl_context))
- elif exported_proxies == True and ssl_context is None:
- opener = urllib2.build_opener(urllib2.ProxyHandler, CacheHTTPHandler)
- else:
- opener = urllib2.build_opener(CacheHTTPHandler)
-
- urllib2.Request.get_method = head_method
- urllib2.install_opener(opener)
-
- uri = ud.url.split(";")[0]
+ handlers.append(urllib2.HTTPSHandler(context=ssl._create_unverified_context()))
+ opener = urllib2.build_opener(*handlers)
try:
- urllib2.urlopen(uri)
- except:
+ uri = ud.url.split(";")[0]
+ r = urllib2.Request(uri)
+ r.get_method = lambda: "HEAD"
+ opener.open(r)
+ except urllib2.URLError as e:
+ # debug for now to avoid spamming the logs in e.g. remote sstate searches
+ logger.debug(2, "checkstatus() urlopen failed: %s" % e)
return False
return True
@@ -367,7 +381,7 @@ class Wget(FetchMethod):
version = ['', '', '']
bb.debug(3, "VersionURL: %s" % (url))
- soup = BeautifulSoup(self._fetch_index(url, ud, d))
+ soup = BeautifulSoup(self._fetch_index(url, ud, d), "html.parser", parse_only=SoupStrainer("a"))
if not soup:
bb.debug(3, "*** %s NO SOUP" % (url))
return ""
@@ -406,10 +420,10 @@ class Wget(FetchMethod):
version_dir = ['', '', '']
version = ['', '', '']
- dirver_regex = re.compile("(\D*)((\d+[\.\-_])+(\d+))")
+ dirver_regex = re.compile("(?P<pfx>\D*)(?P<ver>(\d+[\.\-_])+(\d+))")
s = dirver_regex.search(dirver)
if s:
- version_dir[1] = s.group(2)
+ version_dir[1] = s.group('ver')
else:
version_dir[1] = dirver
@@ -417,16 +431,26 @@ class Wget(FetchMethod):
ud.path.split(dirver)[0], ud.user, ud.pswd, {}])
bb.debug(3, "DirURL: %s, %s" % (dirs_uri, package))
- soup = BeautifulSoup(self._fetch_index(dirs_uri, ud, d))
+ soup = BeautifulSoup(self._fetch_index(dirs_uri, ud, d), "html.parser", parse_only=SoupStrainer("a"))
if not soup:
return version[1]
for line in soup.find_all('a', href=True):
s = dirver_regex.search(line['href'].strip("/"))
if s:
- version_dir_new = ['', s.group(2), '']
+ sver = s.group('ver')
+
+ # When prefix is part of the version directory it need to
+ # ensure that only version directory is used so remove previous
+ # directories if exists.
+ #
+ # Example: pfx = '/dir1/dir2/v' and version = '2.5' the expected
+ # result is v2.5.
+ spfx = s.group('pfx').split('/')[-1]
+
+ version_dir_new = ['', sver, '']
if self._vercmp(version_dir, version_dir_new) <= 0:
- dirver_new = s.group(1) + s.group(2)
+ dirver_new = spfx + sver
path = ud.path.replace(dirver, dirver_new, True) \
.split(package)[0]
uri = bb.fetch.encodeurl([ud.type, ud.host, path,
@@ -480,7 +504,7 @@ class Wget(FetchMethod):
self.suffix_regex_comp = re.compile(psuffix_regex)
# compile regex, can be specific by package or generic regex
- pn_regex = d.getVar('REGEX', True)
+ pn_regex = d.getVar('UPSTREAM_CHECK_REGEX', True)
if pn_regex:
package_custom_regex_comp = re.compile(pn_regex)
else:
@@ -516,7 +540,7 @@ class Wget(FetchMethod):
bb.debug(3, "latest_versionstring, regex: %s" % (package_regex.pattern))
uri = ""
- regex_uri = d.getVar("REGEX_URI", True)
+ regex_uri = d.getVar("UPSTREAM_CHECK_URI", True)
if not regex_uri:
path = ud.path.split(package)[0]
diff --git a/yocto-poky/bitbake/lib/bb/main.py b/yocto-poky/bitbake/lib/bb/main.py
index c8530fc3d..e30217369 100755
--- a/yocto-poky/bitbake/lib/bb/main.py
+++ b/yocto-poky/bitbake/lib/bb/main.py
@@ -219,6 +219,9 @@ class BitBakeConfigParameters(cookerdata.ConfigParameters):
parser.add_option("", "--no-setscene", help = "Do not run any setscene tasks. sstate will be ignored and everything needed, built.",
action = "store_true", dest = "nosetscene", default = False)
+ parser.add_option("", "--setscene-only", help = "Only run setscene tasks, don't run any real tasks.",
+ action = "store_true", dest = "setsceneonly", default = False)
+
parser.add_option("", "--remote-server", help = "Connect to the specified server.",
action = "store", dest = "remote_server", default = False)
@@ -244,7 +247,7 @@ class BitBakeConfigParameters(cookerdata.ConfigParameters):
if "BBTOKEN" in os.environ:
options.xmlrpctoken = os.environ["BBTOKEN"]
- if "BBEVENTLOG" is os.environ:
+ if "BBEVENTLOG" in os.environ:
options.writeeventlog = os.environ["BBEVENTLOG"]
# fill in proper log name if not supplied
@@ -279,12 +282,13 @@ class BitBakeConfigParameters(cookerdata.ConfigParameters):
def start_server(servermodule, configParams, configuration, features):
server = servermodule.BitBakeServer()
+ single_use = not configParams.server_only
if configParams.bind:
(host, port) = configParams.bind.split(':')
- server.initServer((host, int(port)))
+ server.initServer((host, int(port)), single_use)
configuration.interface = [ server.serverImpl.host, server.serverImpl.port ]
else:
- server.initServer()
+ server.initServer(single_use=single_use)
configuration.interface = []
try:
@@ -406,6 +410,13 @@ def bitbake_main(configParams, configuration):
except Exception as e:
bb.fatal("Could not connect to server %s: %s" % (configParams.remote_server, str(e)))
+ if configParams.kill_server:
+ server_connection.connection.terminateServer()
+ bb.event.ui_queue = []
+ return 0
+
+ server_connection.setupEventQueue()
+
# Restore the environment in case the UI needs it
for k in cleanedvars:
os.environ[k] = cleanedvars[k]
@@ -417,11 +428,6 @@ def bitbake_main(configParams, configuration):
server_connection.terminate()
return 0
- if configParams.kill_server:
- server_connection.connection.terminateServer()
- bb.event.ui_queue = []
- return 0
-
try:
return ui_module.main(server_connection.connection, server_connection.events, configParams)
finally:
diff --git a/yocto-poky/bitbake/lib/bb/methodpool.py b/yocto-poky/bitbake/lib/bb/methodpool.py
index bf2e9f554..49aed3338 100644
--- a/yocto-poky/bitbake/lib/bb/methodpool.py
+++ b/yocto-poky/bitbake/lib/bb/methodpool.py
@@ -19,11 +19,22 @@
from bb.utils import better_compile, better_exec
-def insert_method(modulename, code, fn):
+def insert_method(modulename, code, fn, lineno):
"""
Add code of a module should be added. The methods
will be simply added, no checking will be done
"""
- comp = better_compile(code, modulename, fn )
+ comp = better_compile(code, modulename, fn, lineno=lineno)
better_exec(comp, None, code, fn)
+compilecache = {}
+
+def compile_cache(code):
+ h = hash(code)
+ if h in compilecache:
+ return compilecache[h]
+ return None
+
+def compile_cache_add(code, compileobj):
+ h = hash(code)
+ compilecache[h] = compileobj
diff --git a/yocto-poky/bitbake/lib/bb/parse/__init__.py b/yocto-poky/bitbake/lib/bb/parse/__init__.py
index 67ec71f86..26ae7ead8 100644
--- a/yocto-poky/bitbake/lib/bb/parse/__init__.py
+++ b/yocto-poky/bitbake/lib/bb/parse/__init__.py
@@ -161,8 +161,8 @@ def vars_from_file(mypkg, d):
def get_file_depends(d):
'''Return the dependent files'''
dep_files = []
- depends = d.getVar('__base_depends', True) or []
- depends = depends + (d.getVar('__depends', True) or [])
+ depends = d.getVar('__base_depends', False) or []
+ depends = depends + (d.getVar('__depends', False) or [])
for (fn, _) in depends:
dep_files.append(os.path.abspath(fn))
return " ".join(dep_files)
diff --git a/yocto-poky/bitbake/lib/bb/parse/ast.py b/yocto-poky/bitbake/lib/bb/parse/ast.py
index 11db1801b..5f55af5ef 100644
--- a/yocto-poky/bitbake/lib/bb/parse/ast.py
+++ b/yocto-poky/bitbake/lib/bb/parse/ast.py
@@ -83,7 +83,7 @@ class DataNode(AstNode):
def getFunc(self, key, data):
if 'flag' in self.groupd and self.groupd['flag'] != None:
- return data.getVarFlag(key, self.groupd['flag'], noweakdefault=True)
+ return data.getVarFlag(key, self.groupd['flag'], expand=False, noweakdefault=True)
else:
return data.getVar(key, False, noweakdefault=True, parsing=True)
@@ -141,24 +141,37 @@ class DataNode(AstNode):
class MethodNode(AstNode):
tr_tbl = string.maketrans('/.+-@%&', '_______')
- def __init__(self, filename, lineno, func_name, body):
+ def __init__(self, filename, lineno, func_name, body, python, fakeroot):
AstNode.__init__(self, filename, lineno)
self.func_name = func_name
self.body = body
+ self.python = python
+ self.fakeroot = fakeroot
def eval(self, data):
text = '\n'.join(self.body)
+ funcname = self.func_name
if self.func_name == "__anonymous":
funcname = ("__anon_%s_%s" % (self.lineno, self.filename.translate(MethodNode.tr_tbl)))
+ self.python = True
text = "def %s(d):\n" % (funcname) + text
- bb.methodpool.insert_method(funcname, text, self.filename)
+ bb.methodpool.insert_method(funcname, text, self.filename, self.lineno - len(self.body))
anonfuncs = data.getVar('__BBANONFUNCS', False) or []
anonfuncs.append(funcname)
data.setVar('__BBANONFUNCS', anonfuncs)
- data.setVar(funcname, text, parsing=True)
- else:
- data.setVarFlag(self.func_name, "func", 1)
- data.setVar(self.func_name, text, parsing=True)
+ if data.getVar(funcname, False):
+ # clean up old version of this piece of metadata, as its
+ # flags could cause problems
+ data.delVarFlag(funcname, 'python')
+ data.delVarFlag(funcname, 'fakeroot')
+ if self.python:
+ data.setVarFlag(funcname, "python", "1")
+ if self.fakeroot:
+ data.setVarFlag(funcname, "fakeroot", "1")
+ data.setVarFlag(funcname, "func", 1)
+ data.setVar(funcname, text, parsing=True)
+ data.setVarFlag(funcname, 'filename', self.filename)
+ data.setVarFlag(funcname, 'lineno', str(self.lineno - len(self.body)))
class PythonMethodNode(AstNode):
def __init__(self, filename, lineno, function, modulename, body):
@@ -172,31 +185,12 @@ class PythonMethodNode(AstNode):
# 'this' file. This means we will not parse methods from
# bb classes twice
text = '\n'.join(self.body)
- bb.methodpool.insert_method(self.modulename, text, self.filename)
+ bb.methodpool.insert_method(self.modulename, text, self.filename, self.lineno - len(self.body) - 1)
data.setVarFlag(self.function, "func", 1)
data.setVarFlag(self.function, "python", 1)
data.setVar(self.function, text, parsing=True)
-
-class MethodFlagsNode(AstNode):
- def __init__(self, filename, lineno, key, m):
- AstNode.__init__(self, filename, lineno)
- self.key = key
- self.m = m
-
- def eval(self, data):
- if data.getVar(self.key, False):
- # clean up old version of this piece of metadata, as its
- # flags could cause problems
- data.setVarFlag(self.key, 'python', None)
- data.setVarFlag(self.key, 'fakeroot', None)
- if self.m.group("py") is not None:
- data.setVarFlag(self.key, "python", "1")
- else:
- data.delVarFlag(self.key, "python")
- if self.m.group("fr") is not None:
- data.setVarFlag(self.key, "fakeroot", "1")
- else:
- data.delVarFlag(self.key, "fakeroot")
+ data.setVarFlag(self.function, 'filename', self.filename)
+ data.setVarFlag(self.function, 'lineno', str(self.lineno - len(self.body) - 1))
class ExportFuncsNode(AstNode):
def __init__(self, filename, lineno, fns, classname):
@@ -209,7 +203,7 @@ class ExportFuncsNode(AstNode):
for func in self.n:
calledfunc = self.classname + "_" + func
- if data.getVar(func, False) and not data.getVarFlag(func, 'export_func'):
+ if data.getVar(func, False) and not data.getVarFlag(func, 'export_func', False):
continue
if data.getVar(func, False):
@@ -217,13 +211,15 @@ class ExportFuncsNode(AstNode):
data.setVarFlag(func, 'func', None)
for flag in [ "func", "python" ]:
- if data.getVarFlag(calledfunc, flag):
- data.setVarFlag(func, flag, data.getVarFlag(calledfunc, flag))
+ if data.getVarFlag(calledfunc, flag, False):
+ data.setVarFlag(func, flag, data.getVarFlag(calledfunc, flag, False))
for flag in [ "dirs" ]:
- if data.getVarFlag(func, flag):
- data.setVarFlag(calledfunc, flag, data.getVarFlag(func, flag))
+ if data.getVarFlag(func, flag, False):
+ data.setVarFlag(calledfunc, flag, data.getVarFlag(func, flag, False))
+ data.setVarFlag(func, "filename", "autogenerated")
+ data.setVarFlag(func, "lineno", 1)
- if data.getVarFlag(calledfunc, "python"):
+ if data.getVarFlag(calledfunc, "python", False):
data.setVar(func, " bb.build.exec_func('" + calledfunc + "', d)\n", parsing=True)
else:
if "-" in self.classname:
@@ -278,15 +274,12 @@ def handleExport(statements, filename, lineno, m):
def handleData(statements, filename, lineno, groupd):
statements.append(DataNode(filename, lineno, groupd))
-def handleMethod(statements, filename, lineno, func_name, body):
- statements.append(MethodNode(filename, lineno, func_name, body))
+def handleMethod(statements, filename, lineno, func_name, body, python, fakeroot):
+ statements.append(MethodNode(filename, lineno, func_name, body, python, fakeroot))
def handlePythonMethod(statements, filename, lineno, funcname, modulename, body):
statements.append(PythonMethodNode(filename, lineno, funcname, modulename, body))
-def handleMethodFlags(statements, filename, lineno, key, m):
- statements.append(MethodFlagsNode(filename, lineno, key, m))
-
def handleExportFuncs(statements, filename, lineno, m, classname):
statements.append(ExportFuncsNode(filename, lineno, m.group(1), classname))
@@ -317,7 +310,9 @@ def finalize(fn, d, variant = None):
all_handlers = {}
for var in d.getVar('__BBHANDLERS', False) or []:
# try to add the handler
- bb.event.register(var, d.getVar(var, False), (d.getVarFlag(var, "eventmask", True) or "").split())
+ handlerfn = d.getVarFlag(var, "filename", False)
+ handlerln = int(d.getVarFlag(var, "lineno", False))
+ bb.event.register(var, d.getVar(var, False), (d.getVarFlag(var, "eventmask", True) or "").split(), handlerfn, handlerln)
bb.event.fire(bb.event.RecipePreFinalise(fn), d)
diff --git a/yocto-poky/bitbake/lib/bb/parse/parse_py/BBHandler.py b/yocto-poky/bitbake/lib/bb/parse/parse_py/BBHandler.py
index ec097baf7..ef72c3700 100644
--- a/yocto-poky/bitbake/lib/bb/parse/parse_py/BBHandler.py
+++ b/yocto-poky/bitbake/lib/bb/parse/parse_py/BBHandler.py
@@ -47,7 +47,6 @@ __addhandler_regexp__ = re.compile( r"addhandler\s+(.+)" )
__def_regexp__ = re.compile( r"def\s+(\w+).*:" )
__python_func_regexp__ = re.compile( r"(\s+.*)|(^$)" )
-
__infunc__ = []
__inpython__ = False
__body__ = []
@@ -55,15 +54,6 @@ __classname__ = ""
cached_statements = {}
-# We need to indicate EOF to the feeder. This code is so messy that
-# factoring it out to a close_parse_file method is out of question.
-# We will use the IN_PYTHON_EOF as an indicator to just close the method
-#
-# The two parts using it are tightly integrated anyway
-IN_PYTHON_EOF = -9999999999999
-
-
-
def supports(fn, d):
"""Return True if fn has a supported extension"""
return os.path.splitext(fn)[-1] in [".bb", ".bbclass", ".inc"]
@@ -110,7 +100,7 @@ def get_statements(filename, absolute_filename, base_name):
file.close()
if __inpython__:
# add a blank line to close out any python definition
- feeder(IN_PYTHON_EOF, "", filename, base_name, statements)
+ feeder(lineno, "", filename, base_name, statements, eof=True)
if filename.endswith(".bbclass") or filename.endswith(".inc"):
cached_statements[absolute_filename] = statements
@@ -171,12 +161,12 @@ def handle(fn, d, include):
return d
-def feeder(lineno, s, fn, root, statements):
+def feeder(lineno, s, fn, root, statements, eof=False):
global __func_start_regexp__, __inherit_regexp__, __export_func_regexp__, __addtask_regexp__, __addhandler_regexp__, __def_regexp__, __python_func_regexp__, __inpython__, __infunc__, __body__, bb, __residue__, __classname__
if __infunc__:
if s == '}':
__body__.append('')
- ast.handleMethod(statements, fn, lineno, __infunc__[0], __body__)
+ ast.handleMethod(statements, fn, lineno, __infunc__[0], __body__, __infunc__[3], __infunc__[4])
__infunc__ = []
__body__ = []
else:
@@ -185,7 +175,7 @@ def feeder(lineno, s, fn, root, statements):
if __inpython__:
m = __python_func_regexp__.match(s)
- if m and lineno != IN_PYTHON_EOF:
+ if m and not eof:
__body__.append(s)
return
else:
@@ -194,7 +184,7 @@ def feeder(lineno, s, fn, root, statements):
__body__ = []
__inpython__ = False
- if lineno == IN_PYTHON_EOF:
+ if eof:
return
if s and s[0] == '#':
@@ -221,8 +211,7 @@ def feeder(lineno, s, fn, root, statements):
m = __func_start_regexp__.match(s)
if m:
- __infunc__ = [m.group("func") or "__anonymous", fn, lineno]
- ast.handleMethodFlags(statements, fn, lineno, __infunc__[0], m)
+ __infunc__ = [m.group("func") or "__anonymous", fn, lineno, m.group("py") is not None, m.group("fr") is not None]
return
m = __def_regexp__.match(s)
diff --git a/yocto-poky/bitbake/lib/bb/persist_data.py b/yocto-poky/bitbake/lib/bb/persist_data.py
index 5795bc835..e45042324 100644
--- a/yocto-poky/bitbake/lib/bb/persist_data.py
+++ b/yocto-poky/bitbake/lib/bb/persist_data.py
@@ -201,6 +201,7 @@ class PersistData(object):
def connect(database):
connection = sqlite3.connect(database, timeout=5, isolation_level=None)
connection.execute("pragma synchronous = off;")
+ connection.text_factory = str
return connection
def persist(domain, d):
diff --git a/yocto-poky/bitbake/lib/bb/providers.py b/yocto-poky/bitbake/lib/bb/providers.py
index 637e1fab9..563a091fd 100644
--- a/yocto-poky/bitbake/lib/bb/providers.py
+++ b/yocto-poky/bitbake/lib/bb/providers.py
@@ -121,11 +121,14 @@ def findPreferredProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
preferred_file = None
preferred_ver = None
- localdata = data.createCopy(cfgData)
- localdata.setVar('OVERRIDES', "%s:pn-%s:%s" % (data.getVar('OVERRIDES', localdata), pn, pn))
- bb.data.update_data(localdata)
+ # pn can contain '_', e.g. gcc-cross-x86_64 and an override cannot
+ # hence we do this manually rather than use OVERRIDES
+ preferred_v = cfgData.getVar("PREFERRED_VERSION_pn-%s" % pn, True)
+ if not preferred_v:
+ preferred_v = cfgData.getVar("PREFERRED_VERSION_%s" % pn, True)
+ if not preferred_v:
+ preferred_v = cfgData.getVar("PREFERRED_VERSION", True)
- preferred_v = localdata.getVar('PREFERRED_VERSION', True)
if preferred_v:
m = re.match('(\d+:)*(.*)(_.*)*', preferred_v)
if m:
@@ -223,7 +226,7 @@ def findBestProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
def _filterProviders(providers, item, cfgData, dataCache):
"""
Take a list of providers and filter/reorder according to the
- environment variables and previous build results
+ environment variables
"""
eligible = []
preferred_versions = {}
@@ -280,7 +283,7 @@ def _filterProviders(providers, item, cfgData, dataCache):
def filterProviders(providers, item, cfgData, dataCache):
"""
Take a list of providers and filter/reorder according to the
- environment variables and previous build results
+ environment variables
Takes a "normal" target item
"""
@@ -308,38 +311,56 @@ def filterProviders(providers, item, cfgData, dataCache):
def filterProvidersRunTime(providers, item, cfgData, dataCache):
"""
Take a list of providers and filter/reorder according to the
- environment variables and previous build results
+ environment variables
Takes a "runtime" target item
"""
eligible = _filterProviders(providers, item, cfgData, dataCache)
- # Should use dataCache.preferred here?
- preferred = []
- preferred_vars = []
- pns = {}
- for p in eligible:
- pns[dataCache.pkg_fn[p]] = p
- for p in eligible:
- pn = dataCache.pkg_fn[p]
- provides = dataCache.pn_provides[pn]
- for provide in provides:
- prefervar = cfgData.getVar('PREFERRED_PROVIDER_%s' % provide, True)
- #logger.debug(1, "checking PREFERRED_PROVIDER_%s (value %s) against %s", provide, prefervar, pns.keys())
- if prefervar in pns and pns[prefervar] not in preferred:
- var = "PREFERRED_PROVIDER_%s = %s" % (provide, prefervar)
- logger.verbose("selecting %s to satisfy runtime %s due to %s", prefervar, item, var)
- preferred_vars.append(var)
- pref = pns[prefervar]
- eligible.remove(pref)
- eligible = [pref] + eligible
- preferred.append(pref)
+ # First try and match any PREFERRED_RPROVIDER entry
+ prefervar = cfgData.getVar('PREFERRED_RPROVIDER_%s' % item, True)
+ foundUnique = False
+ if prefervar:
+ for p in eligible:
+ pn = dataCache.pkg_fn[p]
+ if prefervar == pn:
+ logger.verbose("selecting %s to satisfy %s due to PREFERRED_RPROVIDER", pn, item)
+ eligible.remove(p)
+ eligible = [p] + eligible
+ foundUnique = True
+ numberPreferred = 1
break
- numberPreferred = len(preferred)
+ # If we didn't find an RPROVIDER entry, try and infer the provider from PREFERRED_PROVIDER entries
+ # by looking through the provides of each eligible recipe and seeing if a PREFERRED_PROVIDER was set.
+ # This is most useful for virtual/ entries rather than having a RPROVIDER per entry.
+ if not foundUnique:
+ # Should use dataCache.preferred here?
+ preferred = []
+ preferred_vars = []
+ pns = {}
+ for p in eligible:
+ pns[dataCache.pkg_fn[p]] = p
+ for p in eligible:
+ pn = dataCache.pkg_fn[p]
+ provides = dataCache.pn_provides[pn]
+ for provide in provides:
+ prefervar = cfgData.getVar('PREFERRED_PROVIDER_%s' % provide, True)
+ #logger.debug(1, "checking PREFERRED_PROVIDER_%s (value %s) against %s", provide, prefervar, pns.keys())
+ if prefervar in pns and pns[prefervar] not in preferred:
+ var = "PREFERRED_PROVIDER_%s = %s" % (provide, prefervar)
+ logger.verbose("selecting %s to satisfy runtime %s due to %s", prefervar, item, var)
+ preferred_vars.append(var)
+ pref = pns[prefervar]
+ eligible.remove(pref)
+ eligible = [pref] + eligible
+ preferred.append(pref)
+ break
+
+ numberPreferred = len(preferred)
if numberPreferred > 1:
- logger.error("Trying to resolve runtime dependency %s resulted in conflicting PREFERRED_PROVIDER entries being found.\nThe providers found were: %s\nThe PREFERRED_PROVIDER entries resulting in this conflict were: %s", item, preferred, preferred_vars)
+ logger.error("Trying to resolve runtime dependency %s resulted in conflicting PREFERRED_PROVIDER entries being found.\nThe providers found were: %s\nThe PREFERRED_PROVIDER entries resulting in this conflict were: %s. You could set PREFERRED_RPROVIDER_%s" % (item, preferred, preferred_vars, item))
logger.debug(1, "sorted runtime providers for %s are: %s", item, eligible)
@@ -379,3 +400,29 @@ def getRuntimeProviders(dataCache, rdepend):
logger.debug(1, "Assuming %s is a dynamic package, but it may not exist" % rdepend)
return rproviders
+
+
+def buildWorldTargetList(dataCache):
+ """
+ Build package list for "bitbake world"
+ """
+ if dataCache.world_target:
+ return
+
+ logger.debug(1, "collating packages for \"world\"")
+ for f in dataCache.possible_world:
+ terminal = True
+ pn = dataCache.pkg_fn[f]
+
+ for p in dataCache.pn_provides[pn]:
+ if p.startswith('virtual/'):
+ logger.debug(2, "World build skipping %s due to %s provider starting with virtual/", f, p)
+ terminal = False
+ break
+ for pf in dataCache.providers[p]:
+ if dataCache.pkg_fn[pf] != pn:
+ logger.debug(2, "World build skipping %s due to both us and %s providing %s", f, pf, p)
+ terminal = False
+ break
+ if terminal:
+ dataCache.world_target.add(pn)
diff --git a/yocto-poky/bitbake/lib/bb/runqueue.py b/yocto-poky/bitbake/lib/bb/runqueue.py
index 878028aa9..e1b9b2e66 100644
--- a/yocto-poky/bitbake/lib/bb/runqueue.py
+++ b/yocto-poky/bitbake/lib/bb/runqueue.py
@@ -261,6 +261,13 @@ class RunQueueData:
taskname = self.runq_task[task] + task_name_suffix
return "%s, %s" % (fn, taskname)
+ def get_short_user_idstring(self, task, task_name_suffix = ""):
+ fn = self.taskData.fn_index[self.runq_fnid[task]]
+ pn = self.dataCache.pkg_fn[fn]
+ taskname = self.runq_task[task] + task_name_suffix
+ return "%s:%s" % (pn, taskname)
+
+
def get_task_id(self, fnid, taskname):
for listid in xrange(len(self.runq_fnid)):
if self.runq_fnid[listid] == fnid and self.runq_task[listid] == taskname:
@@ -634,23 +641,33 @@ class RunQueueData:
fnid = taskData.build_targets[targetid][0]
fn = taskData.fn_index[fnid]
- self.target_pairs.append((fn, target[1]))
+ task = target[1]
+ parents = False
+ if task.endswith('-'):
+ parents = True
+ task = task[:-1]
+
+ self.target_pairs.append((fn, task))
if fnid in taskData.failed_fnids:
continue
- if target[1] not in taskData.tasks_lookup[fnid]:
+ if task not in taskData.tasks_lookup[fnid]:
import difflib
- close_matches = difflib.get_close_matches(target[1], taskData.tasks_lookup[fnid], cutoff=0.7)
+ close_matches = difflib.get_close_matches(task, taskData.tasks_lookup[fnid], cutoff=0.7)
if close_matches:
extra = ". Close matches:\n %s" % "\n ".join(close_matches)
else:
extra = ""
- bb.msg.fatal("RunQueue", "Task %s does not exist for target %s%s" % (target[1], target[0], extra))
-
- listid = taskData.tasks_lookup[fnid][target[1]]
-
- mark_active(listid, 1)
+ bb.msg.fatal("RunQueue", "Task %s does not exist for target %s%s" % (task, target[0], extra))
+
+ # For tasks called "XXXX-", ony run their dependencies
+ listid = taskData.tasks_lookup[fnid][task]
+ if parents:
+ for i in self.runq_depends[listid]:
+ mark_active(i, 1)
+ else:
+ mark_active(listid, 1)
# Step C - Prune all inactive tasks
#
@@ -743,11 +760,72 @@ class RunQueueData:
seen_pn.append(pn)
else:
bb.fatal("Multiple versions of %s are due to be built (%s). Only one version of a given PN should be built in any given build. You likely need to set PREFERRED_VERSION_%s to select the correct version or don't depend on multiple versions." % (pn, " ".join(prov_list[prov]), pn))
- msg = "Multiple .bb files are due to be built which each provide %s (%s)." % (prov, " ".join(prov_list[prov]))
+ msg = "Multiple .bb files are due to be built which each provide %s:\n %s" % (prov, "\n ".join(prov_list[prov]))
+ #
+ # Construct a list of things which uniquely depend on each provider
+ # since this may help the user figure out which dependency is triggering this warning
+ #
+ msg += "\nA list of tasks depending on these providers is shown and may help explain where the dependency comes from."
+ deplist = {}
+ commondeps = None
+ for provfn in prov_list[prov]:
+ deps = set()
+ for task, fnid in enumerate(self.runq_fnid):
+ fn = taskData.fn_index[fnid]
+ if fn != provfn:
+ continue
+ for dep in self.runq_revdeps[task]:
+ fn = taskData.fn_index[self.runq_fnid[dep]]
+ if fn == provfn:
+ continue
+ deps.add(self.get_short_user_idstring(dep))
+ if not commondeps:
+ commondeps = set(deps)
+ else:
+ commondeps &= deps
+ deplist[provfn] = deps
+ for provfn in deplist:
+ msg += "\n%s has unique dependees:\n %s" % (provfn, "\n ".join(deplist[provfn] - commondeps))
+ #
+ # Construct a list of provides and runtime providers for each recipe
+ # (rprovides has to cover RPROVIDES, PACKAGES, PACKAGES_DYNAMIC)
+ #
+ msg += "\nIt could be that one recipe provides something the other doesn't and should. The following provider and runtime provider differences may be helpful."
+ provide_results = {}
+ rprovide_results = {}
+ commonprovs = None
+ commonrprovs = None
+ for provfn in prov_list[prov]:
+ provides = set(self.dataCache.fn_provides[provfn])
+ rprovides = set()
+ for rprovide in self.dataCache.rproviders:
+ if provfn in self.dataCache.rproviders[rprovide]:
+ rprovides.add(rprovide)
+ for package in self.dataCache.packages:
+ if provfn in self.dataCache.packages[package]:
+ rprovides.add(package)
+ for package in self.dataCache.packages_dynamic:
+ if provfn in self.dataCache.packages_dynamic[package]:
+ rprovides.add(package)
+ if not commonprovs:
+ commonprovs = set(provides)
+ else:
+ commonprovs &= provides
+ provide_results[provfn] = provides
+ if not commonrprovs:
+ commonrprovs = set(rprovides)
+ else:
+ commonrprovs &= rprovides
+ rprovide_results[provfn] = rprovides
+ #msg += "\nCommon provides:\n %s" % ("\n ".join(commonprovs))
+ #msg += "\nCommon rprovides:\n %s" % ("\n ".join(commonrprovs))
+ for provfn in prov_list[prov]:
+ msg += "\n%s has unique provides:\n %s" % (provfn, "\n ".join(provide_results[provfn] - commonprovs))
+ msg += "\n%s has unique rprovides:\n %s" % (provfn, "\n ".join(rprovide_results[provfn] - commonrprovs))
+
if self.warn_multi_bb:
logger.warn(msg)
else:
- msg += "\n This usually means one provides something the other doesn't and should."
logger.error(msg)
# Create a whitelist usable by the stamp checks
@@ -798,7 +876,7 @@ class RunQueueData:
invalidate_task(fn, st, True)
# Create and print to the logs a virtual/xxxx -> PN (fn) table
- virtmap = taskData.get_providermap()
+ virtmap = taskData.get_providermap(prefix="virtual/")
virtpnmap = {}
for v in virtmap:
virtpnmap[v] = self.dataCache.pkg_fn[virtmap[v]]
@@ -819,6 +897,7 @@ class RunQueueData:
procdep.append(self.taskData.fn_index[self.runq_fnid[dep]] + "." + self.runq_task[dep])
self.runq_hash[task] = bb.parse.siggen.get_taskhash(self.taskData.fn_index[self.runq_fnid[task]], self.runq_task[task], procdep, self.dataCache)
+ bb.parse.siggen.writeout_file_checksum_cache()
return len(self.runq_fnid)
def dump_data(self, taskQueue):
@@ -874,6 +953,7 @@ class RunQueue:
if self.cooker.configuration.profile:
magic = "decafbadbad"
if fakeroot:
+ magic = magic + "beef"
fakerootcmd = self.cfgData.getVar("FAKEROOTCMD", True)
fakerootenv = (self.cfgData.getVar("FAKEROOTBASEENV", True) or "").split()
env = os.environ.copy()
@@ -1067,9 +1147,12 @@ class RunQueue:
retval = self.rqexe.execute()
if self.state is runQueueRunInit:
- logger.info("Executing RunQueue Tasks")
- self.rqexe = RunQueueExecuteTasks(self)
- self.state = runQueueRunning
+ if self.cooker.configuration.setsceneonly:
+ self.state = runQueueComplete
+ else:
+ logger.info("Executing RunQueue Tasks")
+ self.rqexe = RunQueueExecuteTasks(self)
+ self.state = runQueueRunning
if self.state is runQueueRunning:
retval = self.rqexe.execute()
@@ -1388,7 +1471,7 @@ class RunQueueExecuteTasks(RunQueueExecute):
self.runq_buildable.append(1)
else:
self.runq_buildable.append(0)
- if len(self.rqdata.runq_revdeps[task]) > 0 and self.rqdata.runq_revdeps[task].issubset(self.rq.scenequeue_covered) and task not in self.rq.scenequeue_notcovered:
+ if len(self.rqdata.runq_revdeps[task]) > 0 and self.rqdata.runq_revdeps[task].issubset(self.rq.scenequeue_covered):
self.rq.scenequeue_covered.add(task)
found = True
@@ -1399,7 +1482,7 @@ class RunQueueExecuteTasks(RunQueueExecute):
continue
logger.debug(1, 'Considering %s (%s): %s' % (task, self.rqdata.get_user_idstring(task), str(self.rqdata.runq_revdeps[task])))
- if len(self.rqdata.runq_revdeps[task]) > 0 and self.rqdata.runq_revdeps[task].issubset(self.rq.scenequeue_covered) and task not in self.rq.scenequeue_notcovered:
+ if len(self.rqdata.runq_revdeps[task]) > 0 and self.rqdata.runq_revdeps[task].issubset(self.rq.scenequeue_covered):
found = True
self.rq.scenequeue_covered.add(task)
@@ -1708,6 +1791,7 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
sq_revdeps_new[point] = set()
if point in self.rqdata.runq_setscene:
sq_revdeps_new[point] = tasks
+ tasks = set()
for dep in self.rqdata.runq_depends[point]:
if point in sq_revdeps[dep]:
sq_revdeps[dep].remove(point)
@@ -2014,9 +2098,6 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
self.rq.scenequeue_covered = set()
for task in oldcovered:
self.rq.scenequeue_covered.add(self.rqdata.runq_setscene[task])
- self.rq.scenequeue_notcovered = set()
- for task in self.scenequeue_notcovered:
- self.rq.scenequeue_notcovered.add(self.rqdata.runq_setscene[task])
logger.debug(1, 'We can skip tasks %s', sorted(self.rq.scenequeue_covered))
diff --git a/yocto-poky/bitbake/lib/bb/server/__init__.py b/yocto-poky/bitbake/lib/bb/server/__init__.py
index da5e48074..538a633fe 100644
--- a/yocto-poky/bitbake/lib/bb/server/__init__.py
+++ b/yocto-poky/bitbake/lib/bb/server/__init__.py
@@ -63,6 +63,9 @@ class BitBakeBaseServerConnection():
def terminate(self):
pass
+ def setupEventQueue(self):
+ pass
+
""" BitBakeBaseServer class is the common ancestor to all Bitbake servers
diff --git a/yocto-poky/bitbake/lib/bb/server/process.py b/yocto-poky/bitbake/lib/bb/server/process.py
index 5fca3508b..a3078a873 100644
--- a/yocto-poky/bitbake/lib/bb/server/process.py
+++ b/yocto-poky/bitbake/lib/bb/server/process.py
@@ -53,10 +53,12 @@ class ServerCommunicator():
while True:
# don't let the user ctrl-c while we're waiting for a response
try:
- if self.connection.poll(20):
- return self.connection.recv()
- else:
- bb.fatal("Timeout while attempting to communicate with bitbake server")
+ for idx in range(0,4): # 0, 1, 2, 3
+ if self.connection.poll(5):
+ return self.connection.recv()
+ else:
+ bb.warn("Timeout while attempting to communicate with bitbake server")
+ bb.fatal("Gave up; Too many tries: timeout while attempting to communicate with bitbake server")
except KeyboardInterrupt:
pass
@@ -106,6 +108,7 @@ class ProcessServer(Process, BaseImplServer):
# the UI and communicated to us
self.quitin.close()
signal.signal(signal.SIGINT, signal.SIG_IGN)
+ bb.utils.set_process_name("Cooker")
while not self.quit:
try:
if self.command_channel.poll():
@@ -212,6 +215,7 @@ class ProcessEventQueue(multiprocessing.queues.Queue):
def __init__(self, maxsize):
multiprocessing.queues.Queue.__init__(self, maxsize)
self.exit = False
+ bb.utils.set_process_name("ProcessEQueue")
def setexit(self):
self.exit = True
@@ -238,7 +242,7 @@ class ProcessEventQueue(multiprocessing.queues.Queue):
class BitBakeServer(BitBakeBaseServer):
- def initServer(self):
+ def initServer(self, single_use=True):
# establish communication channels. We use bidirectional pipes for
# ui <--> server command/response pairs
# and a queue for server -> ui event notifications
diff --git a/yocto-poky/bitbake/lib/bb/server/xmlrpc.py b/yocto-poky/bitbake/lib/bb/server/xmlrpc.py
index b7647c198..ace1cf646 100644
--- a/yocto-poky/bitbake/lib/bb/server/xmlrpc.py
+++ b/yocto-poky/bitbake/lib/bb/server/xmlrpc.py
@@ -97,10 +97,10 @@ class BitBakeServerCommands():
# we don't allow connections if the cooker is running
if (self.cooker.state in [bb.cooker.state.parsing, bb.cooker.state.running]):
- return None
+ return None, "Cooker is busy: %s" % bb.cooker.state.get_name(self.cooker.state)
self.event_handle = bb.event.register_UIHhandler(s, True)
- return self.event_handle
+ return self.event_handle, 'OK'
def unregisterEventHandler(self, handlerNum):
"""
@@ -186,13 +186,12 @@ class XMLRPCServer(SimpleXMLRPCServer, BaseImplServer):
# remove this when you're done with debugging
# allow_reuse_address = True
- def __init__(self, interface):
+ def __init__(self, interface, single_use=False):
"""
Constructor
"""
BaseImplServer.__init__(self)
- if (interface[1] == 0): # anonymous port, not getting reused
- self.single_use = True
+ self.single_use = single_use
# Use auto port configuration
if (interface[1] == -1):
interface = (interface[0], 0)
@@ -205,7 +204,6 @@ class XMLRPCServer(SimpleXMLRPCServer, BaseImplServer):
self.commands = BitBakeServerCommands(self)
self.autoregister_all_functions(self.commands, "")
self.interface = interface
- self.single_use = False
def addcooker(self, cooker):
BaseImplServer.addcooker(self, cooker)
@@ -302,7 +300,9 @@ class BitBakeXMLRPCServerConnection(BitBakeBaseServerConnection):
return None
self.transport.set_connection_token(token)
+ return self
+ def setupEventQueue(self):
self.events = uievent.BBUIEventQueue(self.connection, self.clientinfo)
for event in bb.event.ui_queue:
self.events.queue_event(event)
@@ -314,8 +314,6 @@ class BitBakeXMLRPCServerConnection(BitBakeBaseServerConnection):
# no need to log it here, the error shall be sent to the client
raise BaseException(error)
- return self
-
def removeClient(self):
if not self.observer_only:
self.connection.removeClient()
@@ -334,9 +332,9 @@ class BitBakeXMLRPCServerConnection(BitBakeBaseServerConnection):
pass
class BitBakeServer(BitBakeBaseServer):
- def initServer(self, interface = ("localhost", 0)):
+ def initServer(self, interface = ("localhost", 0), single_use = False):
self.interface = interface
- self.serverImpl = XMLRPCServer(interface)
+ self.serverImpl = XMLRPCServer(interface, single_use)
def detach(self):
daemonize.createDaemon(self.serverImpl.serve_forever, "bitbake-cookerdaemon.log")
diff --git a/yocto-poky/bitbake/lib/bb/siggen.py b/yocto-poky/bitbake/lib/bb/siggen.py
index 0352e4523..88fc0f1d5 100644
--- a/yocto-poky/bitbake/lib/bb/siggen.py
+++ b/yocto-poky/bitbake/lib/bb/siggen.py
@@ -4,6 +4,7 @@ import os
import re
import tempfile
import bb.data
+from bb.checksum import FileChecksumCache
logger = logging.getLogger('BitBake.SigGen')
@@ -37,6 +38,7 @@ class SignatureGenerator(object):
self.taskhash = {}
self.runtaskdeps = {}
self.file_checksum_values = {}
+ self.taints = {}
def finalise(self, fn, d, varient):
return
@@ -44,7 +46,8 @@ class SignatureGenerator(object):
def get_taskhash(self, fn, task, deps, dataCache):
return "0"
- def set_taskdata(self, hashes, deps, checksum):
+ def writeout_file_checksum_cache(self):
+ """Write/update the file checksum cache onto disk"""
return
def stampfile(self, stampbase, file_name, taskname, extrainfo):
@@ -63,10 +66,10 @@ class SignatureGenerator(object):
return
def get_taskdata(self):
- return (self.runtaskdeps, self.taskhash, self.file_checksum_values)
+ return (self.runtaskdeps, self.taskhash, self.file_checksum_values, self.taints)
def set_taskdata(self, data):
- self.runtaskdeps, self.taskhash, self.file_checksum_values = data
+ self.runtaskdeps, self.taskhash, self.file_checksum_values, self.taints = data
class SignatureGeneratorBasic(SignatureGenerator):
@@ -87,6 +90,12 @@ class SignatureGeneratorBasic(SignatureGenerator):
self.basewhitelist = set((data.getVar("BB_HASHBASE_WHITELIST", True) or "").split())
self.taskwhitelist = None
self.init_rundepcheck(data)
+ checksum_cache_file = data.getVar("BB_HASH_CHECKSUM_CACHE_FILE", True)
+ if checksum_cache_file:
+ self.checksum_cache = FileChecksumCache()
+ self.checksum_cache.init_cache(data, checksum_cache_file)
+ else:
+ self.checksum_cache = None
def init_rundepcheck(self, data):
self.taskwhitelist = data.getVar("BB_HASHTASK_WHITELIST", True) or None
@@ -146,7 +155,7 @@ class SignatureGeneratorBasic(SignatureGenerator):
try:
taskdeps = self._build_data(fn, d)
except:
- bb.note("Error during finalise of %s" % fn)
+ bb.warn("Error during finalise of %s" % fn)
raise
#Slow but can be useful for debugging mismatched basehashes
@@ -178,8 +187,9 @@ class SignatureGeneratorBasic(SignatureGenerator):
k = fn + "." + task
data = dataCache.basetaskhash[k]
self.runtaskdeps[k] = []
- self.file_checksum_values[k] = {}
+ self.file_checksum_values[k] = []
recipename = dataCache.pkg_fn[fn]
+
for dep in sorted(deps, key=clean_basepath):
depname = dataCache.pkg_fn[self.pkgnameextract.search(dep).group('fn')]
if not self.rundep_check(fn, recipename, task, dep, depname, dataCache):
@@ -190,9 +200,12 @@ class SignatureGeneratorBasic(SignatureGenerator):
self.runtaskdeps[k].append(dep)
if task in dataCache.file_checksums[fn]:
- checksums = bb.fetch2.get_file_checksums(dataCache.file_checksums[fn][task], recipename)
+ if self.checksum_cache:
+ checksums = self.checksum_cache.get_checksums(dataCache.file_checksums[fn][task], recipename)
+ else:
+ checksums = bb.fetch2.get_file_checksums(dataCache.file_checksums[fn][task], recipename)
for (f,cs) in checksums:
- self.file_checksum_values[k][f] = cs
+ self.file_checksum_values[k].append((f,cs))
if cs:
data = data + cs
@@ -215,10 +228,22 @@ class SignatureGeneratorBasic(SignatureGenerator):
#d.setVar("BB_TASKHASH_task-%s" % task, taskhash[task])
return h
+ def writeout_file_checksum_cache(self):
+ """Write/update the file checksum cache onto disk"""
+ if self.checksum_cache:
+ self.checksum_cache.save_extras()
+ self.checksum_cache.save_merge()
+ else:
+ bb.fetch2.fetcher_parse_save()
+ bb.fetch2.fetcher_parse_done()
+
def dump_sigtask(self, fn, task, stampbase, runtime):
+
k = fn + "." + task
- if runtime == "customfile":
+ referencestamp = stampbase
+ if isinstance(runtime, str) and runtime.startswith("customfile"):
sigfile = stampbase
+ referencestamp = runtime[11:]
elif runtime and k in self.taskhash:
sigfile = stampbase + "." + task + ".sigdata" + "." + self.taskhash[k]
else:
@@ -227,6 +252,7 @@ class SignatureGeneratorBasic(SignatureGenerator):
bb.utils.mkdirhier(os.path.dirname(sigfile))
data = {}
+ data['task'] = task
data['basewhitelist'] = self.basewhitelist
data['taskwhitelist'] = self.taskwhitelist
data['taskdeps'] = self.taskdeps[fn][task]
@@ -242,12 +268,13 @@ class SignatureGeneratorBasic(SignatureGenerator):
if runtime and k in self.taskhash:
data['runtaskdeps'] = self.runtaskdeps[k]
- data['file_checksum_values'] = [(os.path.basename(f), cs) for f,cs in self.file_checksum_values[k].items()]
+ data['file_checksum_values'] = [(os.path.basename(f), cs) for f,cs in self.file_checksum_values[k]]
data['runtaskhashes'] = {}
for dep in data['runtaskdeps']:
data['runtaskhashes'][dep] = self.taskhash[dep]
+ data['taskhash'] = self.taskhash[k]
- taint = self.read_taint(fn, task, stampbase)
+ taint = self.read_taint(fn, task, referencestamp)
if taint:
data['taint'] = taint
@@ -269,6 +296,15 @@ class SignatureGeneratorBasic(SignatureGenerator):
pass
raise err
+ computed_basehash = calc_basehash(data)
+ if computed_basehash != self.basehash[k]:
+ bb.error("Basehash mismatch %s verses %s for %s" % (computed_basehash, self.basehash[k], k))
+ if k in self.taskhash:
+ computed_taskhash = calc_taskhash(data)
+ if computed_taskhash != self.taskhash[k]:
+ bb.error("Taskhash mismatch %s verses %s for %s" % (computed_taskhash, self.taskhash[k], k))
+
+
def dump_sigs(self, dataCache, options):
for fn in self.taskdeps:
for task in self.taskdeps[fn]:
@@ -308,7 +344,8 @@ def dump_this_task(outfile, d):
import bb.parse
fn = d.getVar("BB_FILENAME", True)
task = "do_" + d.getVar("BB_CURRENTTASK", True)
- bb.parse.siggen.dump_sigtask(fn, task, outfile, "customfile")
+ referencestamp = bb.build.stamp_internal(task, d, None, True)
+ bb.parse.siggen.dump_sigtask(fn, task, outfile, "customfile:" + referencestamp)
def clean_basepath(a):
b = a.rsplit("/", 2)[1] + a.rsplit("/", 2)[2]
@@ -485,6 +522,40 @@ def compare_sigfiles(a, b, recursecb = None):
return output
+def calc_basehash(sigdata):
+ task = sigdata['task']
+ basedata = sigdata['varvals'][task]
+
+ if basedata is None:
+ basedata = ''
+
+ alldeps = sigdata['taskdeps']
+ for dep in alldeps:
+ basedata = basedata + dep
+ val = sigdata['varvals'][dep]
+ if val is not None:
+ basedata = basedata + str(val)
+
+ return hashlib.md5(basedata).hexdigest()
+
+def calc_taskhash(sigdata):
+ data = sigdata['basehash']
+
+ for dep in sigdata['runtaskdeps']:
+ data = data + sigdata['runtaskhashes'][dep]
+
+ for c in sigdata['file_checksum_values']:
+ data = data + c[1]
+
+ if 'taint' in sigdata:
+ if 'nostamp:' in sigdata['taint']:
+ data = data + sigdata['taint'][8:]
+ else:
+ data = data + sigdata['taint']
+
+ return hashlib.md5(data).hexdigest()
+
+
def dump_sigfile(a):
output = []
@@ -518,17 +589,13 @@ def dump_sigfile(a):
if 'taint' in a_data:
output.append("Tainted (by forced/invalidated task): %s" % a_data['taint'])
- data = a_data['basehash']
- for dep in a_data['runtaskdeps']:
- data = data + a_data['runtaskhashes'][dep]
-
- for c in a_data['file_checksum_values']:
- data = data + c[1]
-
- if 'taint' in a_data:
- data = data + a_data['taint']
+ if 'task' in a_data:
+ computed_basehash = calc_basehash(a_data)
+ output.append("Computed base hash is %s and from file %s" % (computed_basehash, a_data['basehash']))
+ else:
+ output.append("Unable to compute base hash")
- h = hashlib.md5(data).hexdigest()
- output.append("Computed Hash is %s" % h)
+ computed_taskhash = calc_taskhash(a_data)
+ output.append("Computed task hash is %s" % computed_taskhash)
return output
diff --git a/yocto-poky/bitbake/lib/bb/taskdata.py b/yocto-poky/bitbake/lib/bb/taskdata.py
index 4d12b3325..9ae52d77d 100644
--- a/yocto-poky/bitbake/lib/bb/taskdata.py
+++ b/yocto-poky/bitbake/lib/bb/taskdata.py
@@ -172,6 +172,8 @@ class TaskData:
if fnid in self.tasks_fnid:
return
+ self.add_extra_deps(fn, dataCache)
+
for task in task_deps['tasks']:
# Work out task dependencies
@@ -242,6 +244,21 @@ class TaskData:
self.fail_fnid(fnid)
return
+ def add_extra_deps(self, fn, dataCache):
+ func = dataCache.extradepsfunc.get(fn, None)
+ if func:
+ bb.providers.buildWorldTargetList(dataCache)
+ pn = dataCache.pkg_fn[fn]
+ params = {'deps': dataCache.deps[fn],
+ 'world_target': dataCache.world_target,
+ 'pkg_pn': dataCache.pkg_pn,
+ 'self_pn': pn}
+ funcname = '_%s_calculate_extra_depends' % pn.replace('-', '_')
+ paramlist = ','.join(params.keys())
+ func = 'def %s(%s):\n%s\n\n%s(%s)' % (funcname, paramlist, func, funcname, paramlist)
+ bb.utils.better_exec(func, params)
+
+
def have_build_target(self, target):
"""
Have we a build target matching this name?
@@ -429,7 +446,14 @@ class TaskData:
return
if not item in dataCache.providers:
- bb.event.fire(bb.event.NoProvider(item, dependees=self.get_dependees_str(item), reasons=self.get_reasons(item), close_matches=self.get_close_matches(item, dataCache.providers.keys())), cfgData)
+ close_matches = self.get_close_matches(item, dataCache.providers.keys())
+ # Is it in RuntimeProviders ?
+ all_p = bb.providers.getRuntimeProviders(dataCache, item)
+ for fn in all_p:
+ new = dataCache.pkg_fn[fn] + " RPROVIDES " + item
+ if new not in close_matches:
+ close_matches.append(new)
+ bb.event.fire(bb.event.NoProvider(item, dependees=self.get_dependees_str(item), reasons=self.get_reasons(item), close_matches=close_matches), cfgData)
raise bb.providers.NoProvider(item)
if self.have_build_target(item):
@@ -612,17 +636,16 @@ class TaskData:
break
# self.dump_data()
- def get_providermap(self):
- virts = []
- virtmap = {}
-
+ def get_providermap(self, prefix=None):
+ provmap = {}
for name in self.build_names_index:
- if name.startswith("virtual/"):
- virts.append(name)
- for v in virts:
- if self.have_build_target(v):
- virtmap[v] = self.fn_index[self.get_provider(v)[0]]
- return virtmap
+ if prefix and not name.startswith(prefix):
+ continue
+ if self.have_build_target(name):
+ provider = self.get_provider(name)
+ if provider:
+ provmap[name] = self.fn_index[provider[0]]
+ return provmap
def dump_data(self):
"""
diff --git a/yocto-poky/bitbake/lib/bb/tests/codeparser.py b/yocto-poky/bitbake/lib/bb/tests/codeparser.py
index 4454bc51e..bb820e403 100644
--- a/yocto-poky/bitbake/lib/bb/tests/codeparser.py
+++ b/yocto-poky/bitbake/lib/bb/tests/codeparser.py
@@ -293,7 +293,12 @@ bb.data.getVar(a(), d, False)
def test_python(self):
self.d.setVar("FOO", self.pydata)
self.setEmptyVars(["inexpand", "a", "test2", "test"])
- self.d.setVarFlags("FOO", {"func": True, "python": True})
+ self.d.setVarFlags("FOO", {
+ "func": True,
+ "python": True,
+ "lineno": 1,
+ "filename": "example.bb",
+ })
deps, values = bb.data.build_dependencies("FOO", set(self.d.keys()), set(), set(), self.d)
diff --git a/yocto-poky/bitbake/lib/bb/tests/data.py b/yocto-poky/bitbake/lib/bb/tests/data.py
index e9aab577f..12232305c 100644
--- a/yocto-poky/bitbake/lib/bb/tests/data.py
+++ b/yocto-poky/bitbake/lib/bb/tests/data.py
@@ -80,6 +80,11 @@ class DataExpansions(unittest.TestCase):
val = self.d.expand("${@d.getVar('foo', True) + ' ${bar}'}")
self.assertEqual(str(val), "value_of_foo value_of_bar")
+ def test_python_unexpanded(self):
+ self.d.setVar("bar", "${unsetvar}")
+ val = self.d.expand("${@d.getVar('foo', True) + ' ${bar}'}")
+ self.assertEqual(str(val), "${@d.getVar('foo', True) + ' ${unsetvar}'}")
+
def test_python_snippet_syntax_error(self):
self.d.setVar("FOO", "${@foo = 5}")
self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
@@ -394,13 +399,13 @@ class TestFlags(unittest.TestCase):
self.d.setVarFlag("foo", "flag2", "value of flag2")
def test_setflag(self):
- self.assertEqual(self.d.getVarFlag("foo", "flag1"), "value of flag1")
- self.assertEqual(self.d.getVarFlag("foo", "flag2"), "value of flag2")
+ self.assertEqual(self.d.getVarFlag("foo", "flag1", False), "value of flag1")
+ self.assertEqual(self.d.getVarFlag("foo", "flag2", False), "value of flag2")
def test_delflag(self):
self.d.delVarFlag("foo", "flag2")
- self.assertEqual(self.d.getVarFlag("foo", "flag1"), "value of flag1")
- self.assertEqual(self.d.getVarFlag("foo", "flag2"), None)
+ self.assertEqual(self.d.getVarFlag("foo", "flag1", False), "value of flag1")
+ self.assertEqual(self.d.getVarFlag("foo", "flag2", False), None)
class Contains(unittest.TestCase):
diff --git a/yocto-poky/bitbake/lib/bb/tests/fetch.py b/yocto-poky/bitbake/lib/bb/tests/fetch.py
index 94173c14a..4ba688bfe 100644
--- a/yocto-poky/bitbake/lib/bb/tests/fetch.py
+++ b/yocto-poky/bitbake/lib/bb/tests/fetch.py
@@ -228,7 +228,38 @@ class URITest(unittest.TestCase):
'params': {},
'query': {},
'relative': False
+ },
+ "http://somesite.net;someparam=1": {
+ 'uri': 'http://somesite.net;someparam=1',
+ 'scheme': 'http',
+ 'hostname': 'somesite.net',
+ 'port': None,
+ 'hostport': 'somesite.net',
+ 'path': '',
+ 'userinfo': '',
+ 'userinfo': '',
+ 'username': '',
+ 'password': '',
+ 'params': {"someparam" : "1"},
+ 'query': {},
+ 'relative': False
+ },
+ "file://somelocation;someparam=1": {
+ 'uri': 'file:somelocation;someparam=1',
+ 'scheme': 'file',
+ 'hostname': '',
+ 'port': None,
+ 'hostport': '',
+ 'path': 'somelocation',
+ 'userinfo': '',
+ 'userinfo': '',
+ 'username': '',
+ 'password': '',
+ 'params': {"someparam" : "1"},
+ 'query': {},
+ 'relative': True
}
+
}
def test_uri(self):
@@ -451,9 +482,7 @@ class FetcherLocalTest(FetcherTest):
def test_local_wildcard(self):
tree = self.fetchUnpack(['file://a', 'file://dir/*'])
- # FIXME: this is broken - it should return ['a', 'dir/c', 'dir/d', 'dir/subdir/e']
- # see https://bugzilla.yoctoproject.org/show_bug.cgi?id=6128
- self.assertEqual(tree, ['a', 'b', 'dir/c', 'dir/d', 'dir/subdir/e'])
+ self.assertEqual(tree, ['a', 'dir/c', 'dir/d', 'dir/subdir/e'])
def test_local_dir(self):
tree = self.fetchUnpack(['file://a', 'file://dir'])
@@ -461,17 +490,15 @@ class FetcherLocalTest(FetcherTest):
def test_local_subdir(self):
tree = self.fetchUnpack(['file://dir/subdir'])
- # FIXME: this is broken - it should return ['dir/subdir/e']
- # see https://bugzilla.yoctoproject.org/show_bug.cgi?id=6129
- self.assertEqual(tree, ['subdir/e'])
+ self.assertEqual(tree, ['dir/subdir/e'])
def test_local_subdir_file(self):
tree = self.fetchUnpack(['file://dir/subdir/e'])
self.assertEqual(tree, ['dir/subdir/e'])
def test_local_subdirparam(self):
- tree = self.fetchUnpack(['file://a;subdir=bar'])
- self.assertEqual(tree, ['bar/a'])
+ tree = self.fetchUnpack(['file://a;subdir=bar', 'file://dir;subdir=foo/moo'])
+ self.assertEqual(tree, ['bar/a', 'foo/moo/dir/c', 'foo/moo/dir/d', 'foo/moo/dir/subdir/e'])
def test_local_deepsubdirparam(self):
tree = self.fetchUnpack(['file://dir/subdir/e;subdir=bar'])
@@ -584,42 +611,49 @@ class FetcherNetworkTest(FetcherTest):
os.chdir(os.path.dirname(self.unpackdir))
fetcher.unpack(self.unpackdir)
- def test_trusted_network(self):
- # Ensure trusted_network returns False when the host IS in the list.
- url = "git://Someserver.org/foo;rev=1"
- self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org someserver.org server2.org server3.org")
- self.assertTrue(bb.fetch.trusted_network(self.d, url))
-
- def test_wild_trusted_network(self):
- # Ensure trusted_network returns true when the *.host IS in the list.
- url = "git://Someserver.org/foo;rev=1"
- self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org *.someserver.org server2.org server3.org")
- self.assertTrue(bb.fetch.trusted_network(self.d, url))
-
- def test_prefix_wild_trusted_network(self):
- # Ensure trusted_network returns true when the prefix matches *.host.
- url = "git://git.Someserver.org/foo;rev=1"
- self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org *.someserver.org server2.org server3.org")
- self.assertTrue(bb.fetch.trusted_network(self.d, url))
-
- def test_two_prefix_wild_trusted_network(self):
- # Ensure trusted_network returns true when the prefix matches *.host.
- url = "git://something.git.Someserver.org/foo;rev=1"
- self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org *.someserver.org server2.org server3.org")
- self.assertTrue(bb.fetch.trusted_network(self.d, url))
-
- def test_untrusted_network(self):
- # Ensure trusted_network returns False when the host is NOT in the list.
- url = "git://someserver.org/foo;rev=1"
- self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org server2.org server3.org")
- self.assertFalse(bb.fetch.trusted_network(self.d, url))
-
- def test_wild_untrusted_network(self):
- # Ensure trusted_network returns False when the host is NOT in the list.
- url = "git://*.someserver.org/foo;rev=1"
- self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org server2.org server3.org")
- self.assertFalse(bb.fetch.trusted_network(self.d, url))
+class TrustedNetworksTest(FetcherTest):
+ def test_trusted_network(self):
+ # Ensure trusted_network returns False when the host IS in the list.
+ url = "git://Someserver.org/foo;rev=1"
+ self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org someserver.org server2.org server3.org")
+ self.assertTrue(bb.fetch.trusted_network(self.d, url))
+
+ def test_wild_trusted_network(self):
+ # Ensure trusted_network returns true when the *.host IS in the list.
+ url = "git://Someserver.org/foo;rev=1"
+ self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org *.someserver.org server2.org server3.org")
+ self.assertTrue(bb.fetch.trusted_network(self.d, url))
+
+ def test_prefix_wild_trusted_network(self):
+ # Ensure trusted_network returns true when the prefix matches *.host.
+ url = "git://git.Someserver.org/foo;rev=1"
+ self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org *.someserver.org server2.org server3.org")
+ self.assertTrue(bb.fetch.trusted_network(self.d, url))
+
+ def test_two_prefix_wild_trusted_network(self):
+ # Ensure trusted_network returns true when the prefix matches *.host.
+ url = "git://something.git.Someserver.org/foo;rev=1"
+ self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org *.someserver.org server2.org server3.org")
+ self.assertTrue(bb.fetch.trusted_network(self.d, url))
+
+ def test_port_trusted_network(self):
+ # Ensure trusted_network returns True, even if the url specifies a port.
+ url = "git://someserver.org:8080/foo;rev=1"
+ self.d.setVar("BB_ALLOWED_NETWORKS", "someserver.org")
+ self.assertTrue(bb.fetch.trusted_network(self.d, url))
+
+ def test_untrusted_network(self):
+ # Ensure trusted_network returns False when the host is NOT in the list.
+ url = "git://someserver.org/foo;rev=1"
+ self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org server2.org server3.org")
+ self.assertFalse(bb.fetch.trusted_network(self.d, url))
+
+ def test_wild_untrusted_network(self):
+ # Ensure trusted_network returns False when the host is NOT in the list.
+ url = "git://*.someserver.org/foo;rev=1"
+ self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org server2.org server3.org")
+ self.assertFalse(bb.fetch.trusted_network(self.d, url))
class URLHandle(unittest.TestCase):
@@ -627,11 +661,18 @@ class URLHandle(unittest.TestCase):
"http://www.google.com/index.html" : ('http', 'www.google.com', '/index.html', '', '', {}),
"cvs://anoncvs@cvs.handhelds.org/cvs;module=familiar/dist/ipkg" : ('cvs', 'cvs.handhelds.org', '/cvs', 'anoncvs', '', {'module': 'familiar/dist/ipkg'}),
"cvs://anoncvs:anonymous@cvs.handhelds.org/cvs;tag=V0-99-81;module=familiar/dist/ipkg" : ('cvs', 'cvs.handhelds.org', '/cvs', 'anoncvs', 'anonymous', {'tag': 'V0-99-81', 'module': 'familiar/dist/ipkg'}),
- "git://git.openembedded.org/bitbake;branch=@foo" : ('git', 'git.openembedded.org', '/bitbake', '', '', {'branch': '@foo'})
+ "git://git.openembedded.org/bitbake;branch=@foo" : ('git', 'git.openembedded.org', '/bitbake', '', '', {'branch': '@foo'}),
+ "file://somelocation;someparam=1": ('file', '', 'somelocation', '', '', {'someparam': '1'}),
}
+ # we require a pathname to encodeurl but users can still pass such urls to
+ # decodeurl and we need to handle them
+ decodedata = datatable.copy()
+ decodedata.update({
+ "http://somesite.net;someparam=1": ('http', 'somesite.net', '', '', '', {'someparam': '1'}),
+ })
def test_decodeurl(self):
- for k, v in self.datatable.items():
+ for k, v in self.decodedata.items():
result = bb.fetch.decodeurl(k)
self.assertEqual(result, v)
@@ -663,7 +704,7 @@ class FetchLatestVersionTest(FetcherTest):
# version pattern "yyyymmdd"
("mobile-broadband-provider-info", "git://git.gnome.org/mobile-broadband-provider-info", "4ed19e11c2975105b71b956440acdb25d46a347d", "")
: "20120614",
- # packages with a valid GITTAGREGEX
+ # packages with a valid UPSTREAM_CHECK_GITTAGREGEX
("xf86-video-omap", "git://anongit.freedesktop.org/xorg/driver/xf86-video-omap", "ae0394e687f1a77e966cf72f895da91840dffb8f", "(?P<pver>(\d+\.(\d\.?)*))")
: "0.4.3",
("build-appliance-image", "git://git.yoctoproject.org/poky", "b37dd451a52622d5b570183a81583cc34c2ff555", "(?P<pver>(([0-9][\.|_]?)+[0-9]))")
@@ -692,8 +733,8 @@ class FetchLatestVersionTest(FetcherTest):
: "5.0",
("xserver-xorg", "http://xorg.freedesktop.org/releases/individual/xserver/xorg-server-1.15.1.tar.bz2", "", "")
: "1.15.1",
- # packages with valid REGEX_URI and REGEX
- ("cups", "http://www.cups.org/software/1.7.2/cups-1.7.2-source.tar.bz2", "http://www.cups.org/software.php", "(?P<name>cups\-)(?P<pver>((\d+[\.\-_]*)+))\-source\.tar\.gz")
+ # packages with valid UPSTREAM_CHECK_URI and UPSTREAM_CHECK_REGEX
+ ("cups", "http://www.cups.org/software/1.7.2/cups-1.7.2-source.tar.bz2", "https://github.com/apple/cups/releases", "(?P<name>cups\-)(?P<pver>((\d+[\.\-_]*)+))\-source\.tar\.gz")
: "2.0.0",
("db", "http://download.oracle.com/berkeley-db/db-5.3.21.tar.gz", "http://www.oracle.com/technetwork/products/berkeleydb/downloads/index-082944.html", "http://download.oracle.com/otn/berkeley-db/(?P<name>db-)(?P<pver>((\d+[\.\-_]*)+))\.tar\.gz")
: "6.1.19",
@@ -705,7 +746,7 @@ class FetchLatestVersionTest(FetcherTest):
for k, v in self.test_git_uris.items():
self.d.setVar("PN", k[0])
self.d.setVar("SRCREV", k[2])
- self.d.setVar("GITTAGREGEX", k[3])
+ self.d.setVar("UPSTREAM_CHECK_GITTAGREGEX", k[3])
ud = bb.fetch2.FetchData(k[1], self.d)
pupver= ud.method.latest_versionstring(ud, self.d)
verstring = pupver[0]
@@ -715,8 +756,8 @@ class FetchLatestVersionTest(FetcherTest):
def test_wget_latest_versionstring(self):
for k, v in self.test_wget_uris.items():
self.d.setVar("PN", k[0])
- self.d.setVar("REGEX_URI", k[2])
- self.d.setVar("REGEX", k[3])
+ self.d.setVar("UPSTREAM_CHECK_URI", k[2])
+ self.d.setVar("UPSTREAM_CHECK_REGEX", k[3])
ud = bb.fetch2.FetchData(k[1], self.d)
pupver = ud.method.latest_versionstring(ud, self.d)
verstring = pupver[0]
@@ -738,6 +779,8 @@ class FetchCheckStatusTest(FetcherTest):
"ftp://ftp.gnu.org/gnu/autoconf/autoconf-2.60.tar.gz",
"ftp://ftp.gnu.org/gnu/chess/gnuchess-5.08.tar.gz",
"ftp://ftp.gnu.org/gnu/gmp/gmp-4.0.tar.gz",
+ # GitHub releases are hosted on Amazon S3, which doesn't support HEAD
+ "https://github.com/kergoth/tslib/releases/download/1.1/tslib-1.1.tar.xz"
]
if os.environ.get("BB_SKIP_NETTESTS") == "yes":
diff --git a/yocto-poky/bitbake/lib/bb/tests/utils.py b/yocto-poky/bitbake/lib/bb/tests/utils.py
index a035ccf17..2f4ccf3c6 100644
--- a/yocto-poky/bitbake/lib/bb/tests/utils.py
+++ b/yocto-poky/bitbake/lib/bb/tests/utils.py
@@ -23,6 +23,7 @@ import unittest
import bb
import os
import tempfile
+import re
class VerCmpString(unittest.TestCase):
@@ -176,7 +177,7 @@ do_functionname() {
# Test file doesn't get modified with some the same values
self._testeditfile({'THIS': ('that', None, 0, True),
'OTHER': ('anothervalue', None, 0, True),
- 'MULTILINE3': (' c1 c2 c3', None, 4, False)}, self._origfile)
+ 'MULTILINE3': (' c1 c2 c3 ', None, 4, False)}, self._origfile)
def test_edit_metadata_file_1(self):
@@ -377,6 +378,27 @@ do_functionname() {
self.assertTrue(updated, 'List should be updated but isn\'t')
self.assertEqual(newlines, newfile5.splitlines(True))
+ # Make sure the orig value matches what we expect it to be
+ def test_edit_metadata_origvalue(self):
+ origfile = """
+MULTILINE = " stuff \\
+ morestuff"
+"""
+ expected_value = "stuff morestuff"
+ global value_in_callback
+ value_in_callback = ""
+
+ def handle_var(varname, origvalue, op, newlines):
+ global value_in_callback
+ value_in_callback = origvalue
+ return (origvalue, op, -1, False)
+
+ bb.utils.edit_metadata(origfile.splitlines(True),
+ ['MULTILINE'],
+ handle_var)
+
+ testvalue = re.sub('\s+', ' ', value_in_callback.strip())
+ self.assertEqual(expected_value, testvalue)
class EditBbLayersConf(unittest.TestCase):
diff --git a/yocto-poky/bitbake/lib/bb/ui/buildinfohelper.py b/yocto-poky/bitbake/lib/bb/ui/buildinfohelper.py
index 78f1e9274..93979054d 100644
--- a/yocto-poky/bitbake/lib/bb/ui/buildinfohelper.py
+++ b/yocto-poky/bitbake/lib/bb/ui/buildinfohelper.py
@@ -24,6 +24,7 @@ import os
os.environ["DJANGO_SETTINGS_MODULE"] = "toaster.toastermain.settings"
+import django
from django.utils import timezone
@@ -33,20 +34,23 @@ def _configure_toaster():
sys.path.append(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'toaster'))
_configure_toaster()
-from toaster.orm.models import Build, Task, Recipe, Layer_Version, Layer, Target, LogMessage, HelpText
-from toaster.orm.models import Target_Image_File, BuildArtifact
-from toaster.orm.models import Variable, VariableHistory
-from toaster.orm.models import Package, Package_File, Target_Installed_Package, Target_File
-from toaster.orm.models import Task_Dependency, Package_Dependency
-from toaster.orm.models import Recipe_Dependency
+django.setup()
+
+from orm.models import Build, Task, Recipe, Layer_Version, Layer, Target, LogMessage, HelpText
+from orm.models import Target_Image_File, BuildArtifact
+from orm.models import Variable, VariableHistory
+from orm.models import Package, Package_File, Target_Installed_Package, Target_File
+from orm.models import Task_Dependency, Package_Dependency
+from orm.models import Recipe_Dependency, Provides
+from orm.models import Project, CustomImagePackage, CustomImageRecipe
-from toaster.orm.models import Project
from bldcontrol.models import BuildEnvironment, BuildRequest
from bb.msg import BBLogFormatter as formatter
from django.db import models
from pprint import pformat
import logging
+from datetime import datetime, timedelta
from django.db import transaction, connection
@@ -117,6 +121,12 @@ class ORMWrapper(object):
return vars(self)[dictname][key]
+ def _timestamp_to_datetime(self, secs):
+ """
+ Convert timestamp in seconds to Python datetime
+ """
+ return datetime(1970, 1, 1) + timedelta(seconds=secs)
+
# pylint: disable=no-self-use
# we disable detection of no self use in functions because the methods actually work on the object
# even if they don't touch self anywhere
@@ -146,7 +156,7 @@ class ORMWrapper(object):
prj = Project.objects.get(pk = project_id)
else: # this build was triggered by a legacy system, or command line interactive mode
- prj = Project.objects.get_default_project()
+ prj = Project.objects.get_or_create_default_project()
logger.debug(1, "buildinfohelper: project is not specified, defaulting to %s" % prj)
@@ -208,6 +218,15 @@ class ORMWrapper(object):
assert isinstance(errors, int)
assert isinstance(warnings, int)
+ if build.outcome == Build.CANCELLED:
+ return
+ try:
+ if build.buildrequest.state == BuildRequest.REQ_CANCELLING:
+ return
+ except AttributeError:
+ # We may not have a buildrequest if this is a command line build
+ pass
+
outcome = Build.SUCCEEDED
if errors or taskfailures:
outcome = Build.FAILED
@@ -220,6 +239,30 @@ class ORMWrapper(object):
target.license_manifest_path = license_manifest_path
target.save()
+ def update_task_object(self, build, task_name, recipe_name, task_stats):
+ """
+ Find the task for build which matches the recipe and task name
+ to be stored
+ """
+ task_to_update = Task.objects.get(
+ build = build,
+ task_name = task_name,
+ recipe__name = recipe_name
+ )
+
+ if 'started' in task_stats and 'ended' in task_stats:
+ task_to_update.started = self._timestamp_to_datetime(task_stats['started'])
+ task_to_update.ended = self._timestamp_to_datetime(task_stats['ended'])
+ task_to_update.elapsed_time = (task_stats['ended'] - task_stats['started'])
+ task_to_update.cpu_time_user = task_stats.get('cpu_time_user')
+ task_to_update.cpu_time_system = task_stats.get('cpu_time_system')
+ if 'disk_io_read' in task_stats and 'disk_io_write' in task_stats:
+ task_to_update.disk_io_read = task_stats['disk_io_read']
+ task_to_update.disk_io_write = task_stats['disk_io_write']
+ task_to_update.disk_io = task_stats['disk_io_read'] + task_stats['disk_io_write']
+
+ task_to_update.save()
+
def get_update_task_object(self, task_information, must_exist = False):
assert 'build' in task_information
assert 'recipe' in task_information
@@ -256,14 +299,6 @@ class ORMWrapper(object):
task_object.sstate_result = Task.SSTATE_FAILED
object_changed = True
- # mark down duration if we have a start time and a current time
- if 'start_time' in task_information.keys() and 'end_time' in task_information.keys():
- duration = task_information['end_time'] - task_information['start_time']
- task_object.elapsed_time = duration
- object_changed = True
- del task_information['start_time']
- del task_information['end_time']
-
if object_changed:
task_object.save()
return task_object
@@ -304,18 +339,27 @@ class ORMWrapper(object):
break
- # If we're in analysis mode then we are wholly responsible for the data
+ # If we're in analysis mode or if this is a custom recipe
+ # then we are wholly responsible for the data
# and therefore we return the 'real' recipe rather than the build
# history copy of the recipe.
if recipe_information['layer_version'].build is not None and \
recipe_information['layer_version'].build.project == \
- Project.objects.get_default_project():
+ Project.objects.get_or_create_default_project():
+ return recipe
+
+ if built_recipe is None:
return recipe
return built_recipe
def get_update_layer_version_object(self, build_obj, layer_obj, layer_version_information):
if isinstance(layer_obj, Layer_Version):
+ # Special case the toaster-custom-images layer which is created
+ # on the fly so don't update the values which may cause the layer
+ # to be duplicated on a future get_or_create
+ if layer_obj.layer.name == CustomImageRecipe.LAYER_NAME:
+ return layer_obj
# We already found our layer version for this build so just
# update it with the new build information
logger.debug("We found our layer from toaster")
@@ -325,12 +369,17 @@ class ORMWrapper(object):
# create a new copy of this layer version as a snapshot for
# historical purposes
- layer_copy, c = Layer_Version.objects.get_or_create(build=build_obj,
- layer=layer_obj.layer,
- commit=layer_version_information['commit'],
- local_path = layer_version_information['local_path'],
- )
- logger.info("created new historical layer version %d", layer_copy.pk)
+ layer_copy, c = Layer_Version.objects.get_or_create(
+ build=build_obj,
+ layer=layer_obj.layer,
+ up_branch=layer_obj.up_branch,
+ branch=layer_version_information['branch'],
+ commit=layer_version_information['commit'],
+ local_path=layer_version_information['local_path'],
+ )
+
+ logger.info("created new historical layer version %d",
+ layer_copy.pk)
self.layer_version_built.append(layer_copy)
@@ -346,7 +395,7 @@ class ORMWrapper(object):
# If we're doing a command line build then associate this new layer with the
# project to avoid it 'contaminating' toaster data
project = None
- if build_obj.project == Project.objects.get_default_project():
+ if build_obj.project == Project.objects.get_or_create_default_project():
project = build_obj.project
layer_version_object, _ = Layer_Version.objects.get_or_create(
@@ -445,7 +494,7 @@ class ORMWrapper(object):
parent_obj = self._cached_get(Target_File, target = target_obj, path = parent_path, inodetype = Target_File.ITYPE_DIRECTORY)
tf_obj = Target_File.objects.create(
target = target_obj,
- path = path,
+ path = unicode(path, 'utf-8'),
size = size,
inodetype = Target_File.ITYPE_DIRECTORY,
permission = permission,
@@ -470,7 +519,7 @@ class ORMWrapper(object):
tf_obj = Target_File.objects.create(
target = target_obj,
- path = path,
+ path = unicode(path, 'utf-8'),
size = size,
inodetype = inodetype,
permission = permission,
@@ -501,7 +550,9 @@ class ORMWrapper(object):
filetarget_path = "/".join(fcpl)
try:
- filetarget_obj = Target_File.objects.get(target = target_obj, path = filetarget_path)
+ filetarget_obj = Target_File.objects.get(
+ target = target_obj,
+ path = unicode(filetarget_path, 'utf-8'))
except Target_File.DoesNotExist:
# we might have an invalid link; no way to detect this. just set it to None
filetarget_obj = None
@@ -510,7 +561,7 @@ class ORMWrapper(object):
tf_obj = Target_File.objects.create(
target = target_obj,
- path = path,
+ path = unicode(path, 'utf-8'),
size = size,
inodetype = Target_File.ITYPE_SYMLINK,
permission = permission,
@@ -520,12 +571,14 @@ class ORMWrapper(object):
sym_target = filetarget_obj)
- def save_target_package_information(self, build_obj, target_obj, packagedict, pkgpnmap, recipes):
+ def save_target_package_information(self, build_obj, target_obj, packagedict, pkgpnmap, recipes, built_package=False):
assert isinstance(build_obj, Build)
assert isinstance(target_obj, Target)
errormsg = ""
for p in packagedict:
+ # Search name swtiches round the installed name vs package name
+ # by default installed name == package name
searchname = p
if p not in pkgpnmap:
logger.warning("Image packages list contains %p, but is"
@@ -536,11 +589,38 @@ class ORMWrapper(object):
if 'OPKGN' in pkgpnmap[p].keys():
searchname = pkgpnmap[p]['OPKGN']
- packagedict[p]['object'], created = Package.objects.get_or_create( build = build_obj, name = searchname )
+ built_recipe = recipes[pkgpnmap[p]['PN']]
+
+ if built_package:
+ packagedict[p]['object'], created = Package.objects.get_or_create( build = build_obj, name = searchname )
+ recipe = built_recipe
+ else:
+ packagedict[p]['object'], created = \
+ CustomImagePackage.objects.get_or_create(name=searchname)
+ # Clear the Package_Dependency objects as we're going to update
+ # the CustomImagePackage with the latest dependency information
+ packagedict[p]['object'].package_dependencies_target.all().delete()
+ packagedict[p]['object'].package_dependencies_source.all().delete()
+ try:
+ recipe = self._cached_get(
+ Recipe,
+ name=built_recipe.name,
+ layer_version__build=None,
+ layer_version__up_branch=
+ built_recipe.layer_version.up_branch,
+ file_path=built_recipe.file_path,
+ version=built_recipe.version
+ )
+ except (Recipe.DoesNotExist,
+ Recipe.MultipleObjectsReturned) as e:
+ logger.info("We did not find one recipe for the"
+ "configuration data package %s %s" % (p, e))
+ continue
+
if created or packagedict[p]['object'].size == -1: # save the data anyway we can, not just if it was not created here; bug [YOCTO #6887]
# fill in everything we can from the runtime-reverse package data
try:
- packagedict[p]['object'].recipe = recipes[pkgpnmap[p]['PN']]
+ packagedict[p]['object'].recipe = recipe
packagedict[p]['object'].version = pkgpnmap[p]['PV']
packagedict[p]['object'].installed_name = p
packagedict[p]['object'].revision = pkgpnmap[p]['PR']
@@ -566,7 +646,8 @@ class ORMWrapper(object):
packagedict[p]['object'].installed_size = packagedict[p]['size']
packagedict[p]['object'].save()
- Target_Installed_Package.objects.create(target = target_obj, package = packagedict[p]['object'])
+ if built_package:
+ Target_Installed_Package.objects.create(target = target_obj, package = packagedict[p]['object'])
packagedeps_objs = []
for p in packagedict:
@@ -627,19 +708,37 @@ class ORMWrapper(object):
return log_object.save()
- def save_build_package_information(self, build_obj, package_info, recipes):
- assert isinstance(build_obj, Build)
+ def save_build_package_information(self, build_obj, package_info, recipes,
+ built_package):
+ # assert isinstance(build_obj, Build)
# create and save the object
pname = package_info['PKG']
+ built_recipe = recipes[package_info['PN']]
if 'OPKGN' in package_info.keys():
pname = package_info['OPKGN']
- bp_object, _ = Package.objects.get_or_create( build = build_obj,
- name = pname )
+ if built_package:
+ bp_object, _ = Package.objects.get_or_create( build = build_obj,
+ name = pname )
+ recipe = built_recipe
+ else:
+ bp_object, created = \
+ CustomImagePackage.objects.get_or_create(name=pname)
+ try:
+ recipe = self._cached_get(Recipe,
+ name=built_recipe.name,
+ layer_version__build=None,
+ file_path=built_recipe.file_path,
+ version=built_recipe.version)
+
+ except (Recipe.DoesNotExist, Recipe.MultipleObjectsReturned):
+ logger.debug("We did not find one recipe for the configuration"
+ "data package %s" % pname)
+ return
bp_object.installed_name = package_info['PKG']
- bp_object.recipe = recipes[package_info['PN']]
+ bp_object.recipe = recipe
bp_object.version = package_info['PKGV']
bp_object.revision = package_info['PKGR']
bp_object.summary = package_info['SUMMARY']
@@ -659,7 +758,12 @@ class ORMWrapper(object):
Package_File.objects.bulk_create(packagefile_objects)
def _po_byname(p):
- pkg, created = Package.objects.get_or_create(build = build_obj, name = p)
+ if built_package:
+ pkg, created = Package.objects.get_or_create(build=build_obj,
+ name=p)
+ else:
+ pkg, created = CustomImagePackage.objects.get_or_create(name=p)
+
if created:
pkg.size = -1
pkg.save()
@@ -700,7 +804,6 @@ class ORMWrapper(object):
def save_build_variables(self, build_obj, vardump):
assert isinstance(build_obj, Build)
- helptext_objects = []
for k in vardump:
desc = vardump[k]['doc']
if desc is None:
@@ -711,10 +814,9 @@ class ORMWrapper(object):
if desc is None:
desc = ''
if len(desc):
- helptext_objects.append(HelpText(build=build_obj,
- area=HelpText.VARIABLE,
- key=k,
- text=desc))
+ HelpText.objects.get_or_create(build=build_obj,
+ area=HelpText.VARIABLE,
+ key=k, text=desc)
if not bool(vardump[k]['func']):
value = vardump[k]['v']
if value is None:
@@ -734,8 +836,6 @@ class ORMWrapper(object):
if len(varhist_objects):
VariableHistory.objects.bulk_create(varhist_objects)
- HelpText.objects.bulk_create(helptext_objects)
-
class MockEvent(object):
""" This object is used to create event, for which normal event-processing methods can
@@ -762,7 +862,7 @@ class BuildInfoHelper(object):
# pylint: disable=bad-continuation
# we do not follow the python conventions for continuation indentation due to long lines here
- def __init__(self, server, has_build_history = False):
+ def __init__(self, server, has_build_history = False, brbe = None):
self.internal_state = {}
self.internal_state['taskdata'] = {}
self.internal_state['targets'] = []
@@ -775,8 +875,13 @@ class BuildInfoHelper(object):
self.orm_wrapper = ORMWrapper()
self.has_build_history = has_build_history
self.tmp_dir = self.server.runCommand(["getVariable", "TMPDIR"])[0]
- self.brbe = self.server.runCommand(["getVariable", "TOASTER_BRBE"])[0]
- self.project = self.server.runCommand(["getVariable", "TOASTER_PROJECT"])[0]
+
+ # this is set for Toaster-triggered builds by localhostbecontroller
+ # via toasterui
+ self.brbe = brbe
+
+ self.project = None
+
logger.debug(1, "buildinfohelper: Build info helper inited %s" % vars(self))
@@ -786,8 +891,6 @@ class BuildInfoHelper(object):
def _get_build_information(self, build_log_path):
build_info = {}
- # Generate an identifier for each new build
-
build_info['machine'] = self.server.runCommand(["getVariable", "MACHINE"])[0]
build_info['distro'] = self.server.runCommand(["getVariable", "DISTRO"])[0]
build_info['distro_version'] = self.server.runCommand(["getVariable", "DISTRO_VERSION"])[0]
@@ -796,7 +899,7 @@ class BuildInfoHelper(object):
build_info['cooker_log_path'] = build_log_path
build_info['build_name'] = self.server.runCommand(["getVariable", "BUILDNAME"])[0]
build_info['bitbake_version'] = self.server.runCommand(["getVariable", "BB_VERSION"])[0]
-
+ build_info['project'] = self.project = self.server.runCommand(["getVariable", "TOASTER_PROJECT"])[0]
return build_info
def _get_task_information(self, event, recipe):
@@ -818,44 +921,15 @@ class BuildInfoHelper(object):
assert path.startswith("/")
assert 'build' in self.internal_state
- if self.brbe is None:
- def _slkey_interactive(layer_version):
- assert isinstance(layer_version, Layer_Version)
- return len(layer_version.local_path)
-
- # Heuristics: we always match recipe to the deepest layer path in the discovered layers
- for lvo in sorted(self.orm_wrapper.layer_version_objects, reverse=True, key=_slkey_interactive):
- # we can match to the recipe file path
- if path.startswith(lvo.local_path):
- return lvo
-
- else:
- br_id, be_id = self.brbe.split(":")
- from bldcontrol.bbcontroller import getBuildEnvironmentController
- bc = getBuildEnvironmentController(pk = be_id)
-
- def _slkey_managed(layer_version):
- return len(bc.getGitCloneDirectory(layer_version.giturl, layer_version.commit) + layer_version.dirpath)
-
- # Heuristics: we match the path to where the layers have been checked out
- for brl in sorted(BuildRequest.objects.get(pk = br_id).brlayer_set.all(), reverse = True, key = _slkey_managed):
- localdirname = os.path.join(bc.getGitCloneDirectory(brl.giturl, brl.commit), brl.dirpath)
- # we get a relative path, unless running in HEAD mode where the path is absolute
- if not localdirname.startswith("/"):
- localdirname = os.path.join(bc.be.sourcedir, localdirname)
- if path.startswith(localdirname):
- # If the build request came from toaster this field
- # should contain the information from the layer_version
- # That created this build request.
- if brl.layer_version:
- return brl.layer_version
-
- #logger.warn("-- managed: matched path %s with layer %s " % (path, localdirname))
- # we matched the BRLayer, but we need the layer_version that generated this br
+ def _slkey_interactive(layer_version):
+ assert isinstance(layer_version, Layer_Version)
+ return len(layer_version.local_path)
- for lvo in self.orm_wrapper.layer_version_objects:
- if brl.name == lvo.layer.name:
- return lvo
+ # Heuristics: we always match recipe to the deepest layer path in the discovered layers
+ for lvo in sorted(self.orm_wrapper.layer_version_objects, reverse=True, key=_slkey_interactive):
+ # we can match to the recipe file path
+ if path.startswith(lvo.local_path):
+ return lvo
#if we get here, we didn't read layers correctly; dump whatever information we have on the error log
logger.warn("Could not match layer version for recipe path %s : %s", path, self.orm_wrapper.layer_version_objects)
@@ -890,12 +964,10 @@ class BuildInfoHelper(object):
def _get_path_information(self, task_object):
assert isinstance(task_object, Task)
- build_stats_format = "{tmpdir}/buildstats/{target}-{machine}/{buildname}/{package}/"
+ build_stats_format = "{tmpdir}/buildstats/{buildname}/{package}/"
build_stats_path = []
for t in self.internal_state['targets']:
- target = t.target
- machine = self.internal_state['build'].machine
buildname = self.internal_state['build'].build_name
pe, pv = task_object.recipe.version.split(":",1)
if len(pe) > 0:
@@ -903,8 +975,8 @@ class BuildInfoHelper(object):
else:
package = task_object.recipe.name + "-" + pv
- build_stats_path.append(build_stats_format.format(tmpdir=self.tmp_dir, target=target,
- machine=machine, buildname=buildname,
+ build_stats_path.append(build_stats_format.format(tmpdir=self.tmp_dir,
+ buildname=buildname,
package=package))
return build_stats_path
@@ -938,6 +1010,9 @@ class BuildInfoHelper(object):
assert '_pkgs' in vars(event)
build_information = self._get_build_information(build_log_path)
+ # Update brbe and project as they can be changed for every build
+ self.project = build_information['project']
+
build_obj = self.orm_wrapper.create_build_object(build_information, self.brbe, self.project)
self.internal_state['build'] = build_obj
@@ -1059,31 +1134,11 @@ class BuildInfoHelper(object):
def store_tasks_stats(self, event):
- for (taskfile, taskname, taskstats, recipename) in BuildInfoHelper._get_data_from_event(event):
- localfilepath = taskfile.split(":")[-1]
- assert localfilepath.startswith("/")
+ task_data = BuildInfoHelper._get_data_from_event(event)
- recipe_information = self._get_recipe_information_from_taskfile(taskfile)
- try:
- if recipe_information['file_path'].startswith(recipe_information['layer_version'].local_path):
- recipe_information['file_path'] = recipe_information['file_path'][len(recipe_information['layer_version'].local_path):].lstrip("/")
-
- recipe_object = Recipe.objects.get(layer_version = recipe_information['layer_version'],
- file_path__endswith = recipe_information['file_path'],
- name = recipename)
- except Recipe.DoesNotExist:
- logger.error("Could not find recipe for recipe_information %s name %s" , pformat(recipe_information), recipename)
- raise
-
- task_information = {}
- task_information['build'] = self.internal_state['build']
- task_information['recipe'] = recipe_object
- task_information['task_name'] = taskname
- task_information['cpu_usage'] = taskstats['cpu_usage']
- task_information['disk_io'] = taskstats['disk_io']
- if 'elapsed_time' in taskstats:
- task_information['elapsed_time'] = taskstats['elapsed_time']
- self.orm_wrapper.get_update_task_object(task_information)
+ for (task_file, task_name, task_stats, recipe_name) in task_data:
+ build = self.internal_state['build']
+ self.orm_wrapper.update_task_object(build, task_name, recipe_name, task_stats)
def update_and_store_task(self, event):
assert 'taskfile' in vars(event)
@@ -1105,13 +1160,6 @@ class BuildInfoHelper(object):
recipe = self.orm_wrapper.get_update_recipe_object(recipe_information, True)
task_information = self._get_task_information(event,recipe)
- if 'time' in vars(event):
- if not 'start_time' in self.internal_state['taskdata'][identifier]:
- self.internal_state['taskdata'][identifier]['start_time'] = event.time
- else:
- task_information['end_time'] = event.time
- task_information['start_time'] = self.internal_state['taskdata'][identifier]['start_time']
-
task_information['outcome'] = self.internal_state['taskdata'][identifier]['outcome']
if 'logfile' in vars(event):
@@ -1185,11 +1233,12 @@ class BuildInfoHelper(object):
for target in self.internal_state['targets']:
if target.is_image:
pkgdata = BuildInfoHelper._get_data_from_event(event)['pkgdata']
- imgdata = BuildInfoHelper._get_data_from_event(event)['imgdata'][target.target]
- filedata = BuildInfoHelper._get_data_from_event(event)['filedata'][target.target]
+ imgdata = BuildInfoHelper._get_data_from_event(event)['imgdata'].get(target.target, {})
+ filedata = BuildInfoHelper._get_data_from_event(event)['filedata'].get(target.target, {})
try:
- self.orm_wrapper.save_target_package_information(self.internal_state['build'], target, imgdata, pkgdata, self.internal_state['recipes'])
+ self.orm_wrapper.save_target_package_information(self.internal_state['build'], target, imgdata, pkgdata, self.internal_state['recipes'], built_package=True)
+ self.orm_wrapper.save_target_package_information(self.internal_state['build'], target, imgdata.copy(), pkgdata, self.internal_state['recipes'], built_package=False)
except KeyError as e:
logger.warn("KeyError in save_target_package_information"
"%s ", e)
@@ -1269,6 +1318,9 @@ class BuildInfoHelper(object):
for cls in event._depgraph['pn'][pn]['inherits']:
if cls.endswith('/image.bbclass'):
recipe.is_image = True
+ recipe_info['is_image'] = True
+ # Save the is_image state to the relevant recipe objects
+ self.orm_wrapper.get_update_recipe_object(recipe_info)
break
if recipe.is_image:
for t in self.internal_state['targets']:
@@ -1285,15 +1337,27 @@ class BuildInfoHelper(object):
# buildtime
recipedeps_objects = []
for recipe in event._depgraph['depends']:
- try:
- target = self.internal_state['recipes'][recipe]
- for dep in event._depgraph['depends'][recipe]:
+ target = self.internal_state['recipes'][recipe]
+ for dep in event._depgraph['depends'][recipe]:
+ if dep in assume_provided:
+ continue
+ via = None
+ if 'providermap' in event._depgraph and dep in event._depgraph['providermap']:
+ deprecipe = event._depgraph['providermap'][dep][0]
+ dependency = self.internal_state['recipes'][deprecipe]
+ via = Provides.objects.get_or_create(name=dep,
+ recipe=dependency)[0]
+ elif dep in self.internal_state['recipes']:
dependency = self.internal_state['recipes'][dep]
- recipedeps_objects.append(Recipe_Dependency( recipe = target,
- depends_on = dependency, dep_type = Recipe_Dependency.TYPE_DEPENDS))
- except KeyError as e:
- if e not in assume_provided and not str(e).startswith("virtual/"):
- errormsg += " stpd: KeyError saving recipe dependency for %s, %s \n" % (recipe, e)
+ else:
+ errormsg += " stpd: KeyError saving recipe dependency for %s, %s \n" % (recipe, dep)
+ continue
+ recipe_dep = Recipe_Dependency(recipe=target,
+ depends_on=dependency,
+ via=via,
+ dep_type=Recipe_Dependency.TYPE_DEPENDS)
+ recipedeps_objects.append(recipe_dep)
+
Recipe_Dependency.objects.bulk_create(recipedeps_objects)
# save all task information
@@ -1333,10 +1397,17 @@ class BuildInfoHelper(object):
def store_build_package_information(self, event):
package_info = BuildInfoHelper._get_data_from_event(event)
- self.orm_wrapper.save_build_package_information(self.internal_state['build'],
- package_info,
- self.internal_state['recipes'],
- )
+ self.orm_wrapper.save_build_package_information(
+ self.internal_state['build'],
+ package_info,
+ self.internal_state['recipes'],
+ built_package=True)
+
+ self.orm_wrapper.save_build_package_information(
+ self.internal_state['build'],
+ package_info,
+ self.internal_state['recipes'],
+ built_package=False)
def _store_build_done(self, errorcode):
logger.info("Build exited with errorcode %d", errorcode)
@@ -1345,9 +1416,18 @@ class BuildInfoHelper(object):
be.lock = BuildEnvironment.LOCK_LOCK
be.save()
br = BuildRequest.objects.get(pk = br_id)
+
+ # if we're 'done' because we got cancelled update the build outcome
+ if br.state == BuildRequest.REQ_CANCELLING:
+ logger.info("Build cancelled")
+ br.build.outcome = Build.CANCELLED
+ br.build.save()
+ self.internal_state['build'] = br.build
+ errorcode = 0
+
if errorcode == 0:
# request archival of the project artifacts
- br.state = BuildRequest.REQ_ARCHIVE
+ br.state = BuildRequest.REQ_COMPLETED
else:
br.state = BuildRequest.REQ_FAILED
br.save()
@@ -1434,3 +1514,8 @@ class BuildInfoHelper(object):
if not connection.features.autocommits_when_autocommit_is_off:
transaction.set_autocommit(True)
+
+ # unset the brbe; this is to prevent subsequent command-line builds
+ # being incorrectly attached to the previous Toaster-triggered build;
+ # see https://bugzilla.yoctoproject.org/show_bug.cgi?id=9021
+ self.brbe = None
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/builddetailspage.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/builddetailspage.py
deleted file mode 100755
index 7fc690e2f..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/builddetailspage.py
+++ /dev/null
@@ -1,437 +0,0 @@
-#!/usr/bin/env python
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2012 Intel Corporation
-#
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import gtk
-import pango
-import gobject
-import bb.process
-from bb.ui.crumbs.progressbar import HobProgressBar
-from bb.ui.crumbs.hobwidget import hic, HobNotebook, HobAltButton, HobWarpCellRendererText, HobButton, HobInfoButton
-from bb.ui.crumbs.runningbuild import RunningBuildTreeView
-from bb.ui.crumbs.runningbuild import BuildFailureTreeView
-from bb.ui.crumbs.hobpages import HobPage
-from bb.ui.crumbs.hobcolor import HobColors
-
-class BuildConfigurationTreeView(gtk.TreeView):
- def __init__ (self):
- gtk.TreeView.__init__(self)
- self.set_rules_hint(False)
- self.set_headers_visible(False)
- self.set_property("hover-expand", True)
- self.get_selection().set_mode(gtk.SELECTION_SINGLE)
-
- # The icon that indicates whether we're building or failed.
- renderer0 = gtk.CellRendererText()
- renderer0.set_property('font-desc', pango.FontDescription('courier bold 12'))
- col0 = gtk.TreeViewColumn ("Name", renderer0, text=0)
- self.append_column (col0)
-
- # The message of configuration.
- renderer1 = HobWarpCellRendererText(col_number=1)
- col1 = gtk.TreeViewColumn ("Values", renderer1, text=1)
- self.append_column (col1)
-
- def set_vars(self, key="", var=[""]):
- d = {}
- if type(var) == str:
- d = {key: [var]}
- elif type(var) == list and len(var) > 1:
- #create the sub item line
- l = []
- text = ""
- for item in var:
- text = " - " + item
- l.append(text)
- d = {key: var}
-
- return d
-
- def set_config_model(self, show_vars):
- listmodel = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
- parent = None
- for var in show_vars:
- for subitem in var.items():
- name = subitem[0]
- is_parent = True
- for value in subitem[1]:
- if is_parent:
- parent = listmodel.append(parent, (name, value))
- is_parent = False
- else:
- listmodel.append(parent, (None, value))
- name = " - "
- parent = None
- # renew the tree model after get the configuration messages
- self.set_model(listmodel)
-
- def show(self, src_config_info, src_params):
- vars = []
- vars.append(self.set_vars("BB version:", src_params.bb_version))
- vars.append(self.set_vars("Target arch:", src_params.target_arch))
- vars.append(self.set_vars("Target OS:", src_params.target_os))
- vars.append(self.set_vars("Machine:", src_config_info.curr_mach))
- vars.append(self.set_vars("Distro:", src_config_info.curr_distro))
- vars.append(self.set_vars("Distro version:", src_params.distro_version))
- vars.append(self.set_vars("SDK machine:", src_config_info.curr_sdk_machine))
- vars.append(self.set_vars("Tune features:", src_params.tune_pkgarch))
- vars.append(self.set_vars("Layers:", src_config_info.layers))
-
- for path in src_config_info.layers:
- import os, os.path
- if os.path.exists(path):
- branch = bb.process.run('cd %s; git branch | grep "^* " | tr -d "* "' % path)[0]
- if branch.startswith("fatal:"):
- branch = "(unknown)"
- if branch:
- branch = branch.strip('\n')
- vars.append(self.set_vars("Branch:", branch))
- break
-
- self.set_config_model(vars)
-
- def reset(self):
- self.set_model(None)
-
-#
-# BuildDetailsPage
-#
-
-class BuildDetailsPage (HobPage):
-
- def __init__(self, builder):
- super(BuildDetailsPage, self).__init__(builder, "Building ...")
-
- self.num_of_issues = 0
- self.endpath = (0,)
- # create visual elements
- self.create_visual_elements()
-
- def create_visual_elements(self):
- # create visual elements
- self.vbox = gtk.VBox(False, 12)
-
- self.progress_box = gtk.VBox(False, 12)
- self.task_status = gtk.Label("\n") # to ensure layout is correct
- self.task_status.set_alignment(0.0, 0.5)
- self.progress_box.pack_start(self.task_status, expand=False, fill=False)
- self.progress_hbox = gtk.HBox(False, 6)
- self.progress_box.pack_end(self.progress_hbox, expand=True, fill=True)
- self.progress_bar = HobProgressBar()
- self.progress_hbox.pack_start(self.progress_bar, expand=True, fill=True)
- self.stop_button = HobAltButton("Stop")
- self.stop_button.connect("clicked", self.stop_button_clicked_cb)
- self.stop_button.set_sensitive(False)
- self.progress_hbox.pack_end(self.stop_button, expand=False, fill=False)
-
- self.notebook = HobNotebook()
- self.config_tv = BuildConfigurationTreeView()
- self.scrolled_view_config = gtk.ScrolledWindow ()
- self.scrolled_view_config.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
- self.scrolled_view_config.add(self.config_tv)
- self.notebook.append_page(self.scrolled_view_config, "Build configuration")
-
- self.failure_tv = BuildFailureTreeView()
- self.failure_model = self.builder.handler.build.model.failure_model()
- self.failure_tv.set_model(self.failure_model)
- self.scrolled_view_failure = gtk.ScrolledWindow ()
- self.scrolled_view_failure.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
- self.scrolled_view_failure.add(self.failure_tv)
- self.notebook.append_page(self.scrolled_view_failure, "Issues")
-
- self.build_tv = RunningBuildTreeView(readonly=True, hob=True)
- self.build_tv.set_model(self.builder.handler.build.model)
- self.scrolled_view_build = gtk.ScrolledWindow ()
- self.scrolled_view_build.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
- self.scrolled_view_build.add(self.build_tv)
- self.notebook.append_page(self.scrolled_view_build, "Log")
-
- self.builder.handler.build.model.connect_after("row-changed", self.scroll_to_present_row, self.scrolled_view_build.get_vadjustment(), self.build_tv)
-
- self.button_box = gtk.HBox(False, 6)
- self.back_button = HobAltButton('&lt;&lt; Back')
- self.back_button.connect("clicked", self.back_button_clicked_cb)
- self.button_box.pack_start(self.back_button, expand=False, fill=False)
-
- def update_build_status(self, current, total, task):
- recipe_path, recipe_task = task.split(", ")
- recipe = os.path.basename(recipe_path).rstrip(".bb")
- tsk_msg = "<b>Running task %s of %s:</b> %s\n<b>Recipe:</b> %s" % (current, total, recipe_task, recipe)
- self.task_status.set_markup(tsk_msg)
- self.stop_button.set_sensitive(True)
-
- def reset_build_status(self):
- self.task_status.set_markup("\n") # to ensure layout is correct
- self.endpath = (0,)
-
- def show_issues(self):
- self.num_of_issues += 1
- self.notebook.show_indicator_icon("Issues", self.num_of_issues)
- self.notebook.queue_draw()
-
- def reset_issues(self):
- self.num_of_issues = 0
- self.notebook.hide_indicator_icon("Issues")
-
- def _remove_all_widget(self):
- children = self.vbox.get_children() or []
- for child in children:
- self.vbox.remove(child)
- children = self.box_group_area.get_children() or []
- for child in children:
- self.box_group_area.remove(child)
- children = self.get_children() or []
- for child in children:
- self.remove(child)
-
- def add_build_fail_top_bar(self, actions, log_file=None):
- primary_action = "Edit %s" % actions
-
- color = HobColors.ERROR
- build_fail_top = gtk.EventBox()
- #build_fail_top.set_size_request(-1, 200)
- build_fail_top.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
-
- build_fail_tab = gtk.Table(14, 46, True)
- build_fail_top.add(build_fail_tab)
-
- icon = gtk.Image()
- icon_pix_buffer = gtk.gdk.pixbuf_new_from_file(hic.ICON_INDI_ERROR_FILE)
- icon.set_from_pixbuf(icon_pix_buffer)
- build_fail_tab.attach(icon, 1, 4, 0, 6)
-
- label = gtk.Label()
- label.set_alignment(0.0, 0.5)
- label.set_markup("<span size='x-large'><b>%s</b></span>" % self.title)
- build_fail_tab.attach(label, 4, 26, 0, 6)
-
- label = gtk.Label()
- label.set_alignment(0.0, 0.5)
- # Ensure variable disk_full is defined
- if not hasattr(self.builder, 'disk_full'):
- self.builder.disk_full = False
-
- if self.builder.disk_full:
- markup = "<span size='medium'>There is no disk space left, so Hob cannot finish building your image. Free up some disk space\n"
- markup += "and restart the build. Check the \"Issues\" tab for more details</span>"
- label.set_markup(markup)
- else:
- label.set_markup("<span size='medium'>Check the \"Issues\" information for more details</span>")
- build_fail_tab.attach(label, 4, 40, 4, 9)
-
- # create button 'Edit packages'
- action_button = HobButton(primary_action)
- #action_button.set_size_request(-1, 40)
- action_button.set_tooltip_text("Edit the %s parameters" % actions)
- action_button.connect('clicked', self.failure_primary_action_button_clicked_cb, primary_action)
-
- if log_file:
- open_log_button = HobAltButton("Open log")
- open_log_button.set_relief(gtk.RELIEF_HALF)
- open_log_button.set_tooltip_text("Open the build's log file")
- open_log_button.connect('clicked', self.open_log_button_clicked_cb, log_file)
-
- attach_pos = (24 if log_file else 14)
- file_bug_button = HobAltButton('File a bug')
- file_bug_button.set_relief(gtk.RELIEF_HALF)
- file_bug_button.set_tooltip_text("Open the Yocto Project bug tracking website")
- file_bug_button.connect('clicked', self.failure_activate_file_bug_link_cb)
-
- if not self.builder.disk_full:
- build_fail_tab.attach(action_button, 4, 13, 9, 12)
- if log_file:
- build_fail_tab.attach(open_log_button, 14, 23, 9, 12)
- build_fail_tab.attach(file_bug_button, attach_pos, attach_pos + 9, 9, 12)
-
- else:
- restart_build = HobButton("Restart the build")
- restart_build.set_tooltip_text("Restart the build")
- restart_build.connect('clicked', self.restart_build_button_clicked_cb)
-
- build_fail_tab.attach(restart_build, 4, 13, 9, 12)
- build_fail_tab.attach(action_button, 14, 23, 9, 12)
- if log_file:
- build_fail_tab.attach(open_log_button, attach_pos, attach_pos + 9, 9, 12)
-
- self.builder.disk_full = False
- return build_fail_top
-
- def show_fail_page(self, title):
- self._remove_all_widget()
- self.title = "Hob cannot build your %s" % title
-
- self.build_fail_bar = self.add_build_fail_top_bar(title, self.builder.current_logfile)
-
- self.pack_start(self.group_align, expand=True, fill=True)
- self.box_group_area.pack_start(self.build_fail_bar, expand=False, fill=False)
- self.box_group_area.pack_start(self.vbox, expand=True, fill=True)
-
- self.vbox.pack_start(self.notebook, expand=True, fill=True)
- self.show_all()
- self.notebook.set_page("Issues")
- self.back_button.hide()
-
- def add_build_stop_top_bar(self, action, log_file=None):
- color = HobColors.LIGHT_GRAY
- build_stop_top = gtk.EventBox()
- #build_stop_top.set_size_request(-1, 200)
- build_stop_top.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
- build_stop_top.set_flags(gtk.CAN_DEFAULT)
- build_stop_top.grab_default()
-
- build_stop_tab = gtk.Table(11, 46, True)
- build_stop_top.add(build_stop_tab)
-
- icon = gtk.Image()
- icon_pix_buffer = gtk.gdk.pixbuf_new_from_file(hic.ICON_INFO_HOVER_FILE)
- icon.set_from_pixbuf(icon_pix_buffer)
- build_stop_tab.attach(icon, 1, 4, 0, 6)
-
- label = gtk.Label()
- label.set_alignment(0.0, 0.5)
- label.set_markup("<span size='x-large'><b>%s</b></span>" % self.title)
- build_stop_tab.attach(label, 4, 26, 0, 6)
-
- action_button = HobButton("Edit %s" % action)
- action_button.set_size_request(-1, 40)
- if action == "image":
- action_button.set_tooltip_text("Edit the image parameters")
- elif action == "recipes":
- action_button.set_tooltip_text("Edit the included recipes")
- elif action == "packages":
- action_button.set_tooltip_text("Edit the included packages")
- action_button.connect('clicked', self.stop_primary_action_button_clicked_cb, action)
- build_stop_tab.attach(action_button, 4, 13, 6, 9)
-
- if log_file:
- open_log_button = HobAltButton("Open log")
- open_log_button.set_relief(gtk.RELIEF_HALF)
- open_log_button.set_tooltip_text("Open the build's log file")
- open_log_button.connect('clicked', self.open_log_button_clicked_cb, log_file)
- build_stop_tab.attach(open_log_button, 14, 23, 6, 9)
-
- attach_pos = (24 if log_file else 14)
- build_button = HobAltButton("Build new image")
- #build_button.set_size_request(-1, 40)
- build_button.set_tooltip_text("Create a new image from scratch")
- build_button.connect('clicked', self.new_image_button_clicked_cb)
- build_stop_tab.attach(build_button, attach_pos, attach_pos + 9, 6, 9)
-
- return build_stop_top, action_button
-
- def show_stop_page(self, action):
- self._remove_all_widget()
- self.title = "Build stopped"
- self.build_stop_bar, action_button = self.add_build_stop_top_bar(action, self.builder.current_logfile)
-
- self.pack_start(self.group_align, expand=True, fill=True)
- self.box_group_area.pack_start(self.build_stop_bar, expand=False, fill=False)
- self.box_group_area.pack_start(self.vbox, expand=True, fill=True)
-
- self.vbox.pack_start(self.notebook, expand=True, fill=True)
- self.show_all()
- self.back_button.hide()
- return action_button
-
- def show_page(self, step):
- self._remove_all_widget()
- if step == self.builder.PACKAGE_GENERATING or step == self.builder.FAST_IMAGE_GENERATING:
- self.title = "Building packages ..."
- else:
- self.title = "Building image ..."
- self.build_details_top = self.add_onto_top_bar(None)
- self.pack_start(self.build_details_top, expand=False, fill=False)
- self.pack_start(self.group_align, expand=True, fill=True)
-
- self.box_group_area.pack_start(self.vbox, expand=True, fill=True)
-
- self.progress_bar.reset()
- self.config_tv.reset()
- self.vbox.pack_start(self.progress_box, expand=False, fill=False)
-
- self.vbox.pack_start(self.notebook, expand=True, fill=True)
-
- self.box_group_area.pack_end(self.button_box, expand=False, fill=False)
- self.show_all()
- self.notebook.set_page("Log")
- self.back_button.hide()
-
- self.reset_build_status()
- self.reset_issues()
-
- def update_progress_bar(self, title, fraction, status=None):
- self.progress_bar.update(fraction)
- self.progress_bar.set_title(title)
- self.progress_bar.set_rcstyle(status)
-
- def back_button_clicked_cb(self, button):
- self.builder.show_configuration()
-
- def new_image_button_clicked_cb(self, button):
- self.builder.reset()
-
- def show_back_button(self):
- self.back_button.show()
-
- def stop_button_clicked_cb(self, button):
- self.builder.stop_build()
-
- def hide_stop_button(self):
- self.stop_button.set_sensitive(False)
- self.stop_button.hide()
-
- def scroll_to_present_row(self, model, path, iter, v_adj, treeview):
- if treeview and v_adj:
- if path[0] > self.endpath[0]: # check the event is a new row append or not
- self.endpath = path
- # check the gtk.adjustment position is at end boundary or not
- if (v_adj.upper <= v_adj.page_size) or (v_adj.value == v_adj.upper - v_adj.page_size):
- treeview.scroll_to_cell(path)
-
- def show_configurations(self, configurations, params):
- self.config_tv.show(configurations, params)
-
- def failure_primary_action_button_clicked_cb(self, button, action):
- if "Edit recipes" in action:
- self.builder.show_recipes()
- elif "Edit packages" in action:
- self.builder.show_packages()
- elif "Edit image" in action:
- self.builder.show_configuration()
-
- def restart_build_button_clicked_cb(self, button):
- self.builder.just_bake()
-
- def stop_primary_action_button_clicked_cb(self, button, action):
- if "recipes" in action:
- self.builder.show_recipes()
- elif "packages" in action:
- self.builder.show_packages()
- elif "image" in action:
- self.builder.show_configuration()
-
- def open_log_button_clicked_cb(self, button, log_file):
- if log_file:
- log_file = "file:///" + log_file
- gtk.show_uri(screen=button.get_screen(), uri=log_file, timestamp=0)
-
- def failure_activate_file_bug_link_cb(self, button):
- button.child.emit('activate-link', "http://bugzilla.yoctoproject.org")
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/builder.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/builder.py
deleted file mode 100755
index dcc410426..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/builder.py
+++ /dev/null
@@ -1,1475 +0,0 @@
-#!/usr/bin/env python
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2011-2012 Intel Corporation
-#
-# Authored by Joshua Lock <josh@linux.intel.com>
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import glib
-import gtk, gobject
-import copy
-import os
-import subprocess
-import shlex
-import re
-import logging
-import sys
-import signal
-import time
-from bb.ui.crumbs.imageconfigurationpage import ImageConfigurationPage
-from bb.ui.crumbs.recipeselectionpage import RecipeSelectionPage
-from bb.ui.crumbs.packageselectionpage import PackageSelectionPage
-from bb.ui.crumbs.builddetailspage import BuildDetailsPage
-from bb.ui.crumbs.imagedetailspage import ImageDetailsPage
-from bb.ui.crumbs.sanitycheckpage import SanityCheckPage
-from bb.ui.crumbs.hobwidget import hwc, HobButton, HobAltButton
-from bb.ui.crumbs.persistenttooltip import PersistentTooltip
-import bb.ui.crumbs.utils
-from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog
-from bb.ui.crumbs.hig.simplesettingsdialog import SimpleSettingsDialog
-from bb.ui.crumbs.hig.advancedsettingsdialog import AdvancedSettingsDialog
-from bb.ui.crumbs.hig.deployimagedialog import DeployImageDialog
-from bb.ui.crumbs.hig.layerselectiondialog import LayerSelectionDialog
-from bb.ui.crumbs.hig.imageselectiondialog import ImageSelectionDialog
-from bb.ui.crumbs.hig.parsingwarningsdialog import ParsingWarningsDialog
-from bb.ui.crumbs.hig.propertydialog import PropertyDialog
-
-hobVer = 20120808
-
-class Configuration:
- '''Represents the data structure of configuration.'''
-
- @classmethod
- def parse_proxy_string(cls, proxy):
- pattern = "^\s*((http|https|ftp|socks|cvs)://)?((\S+):(\S+)@)?([^\s:]+)(:(\d+))?/?"
- match = re.search(pattern, proxy)
- if match:
- return match.group(2), match.group(4), match.group(5), match.group(6), match.group(8)
- else:
- return None, None, None, "", ""
-
- @classmethod
- def make_host_string(cls, prot, user, passwd, host, default_prot=""):
- if host == None or host == "":
- return ""
-
- passwd = passwd or ""
-
- if user != None and user != "":
- if prot == None or prot == "":
- prot = default_prot
- return prot + "://" + user + ":" + passwd + "@" + host
- else:
- if prot == None or prot == "":
- return host
- else:
- return prot + "://" + host
-
- @classmethod
- def make_port_string(cls, port):
- port = port or ""
- return port
-
- @classmethod
- def make_proxy_string(cls, prot, user, passwd, host, port, default_prot=""):
- if host == None or host == "":# or port == None or port == "":
- return ""
-
- return Configuration.make_host_string(prot, user, passwd, host, default_prot) + (":" + Configuration.make_port_string(port) if port else "")
-
- def __init__(self):
- self.curr_mach = ""
- self.selected_image = None
- # settings
- self.curr_distro = ""
- self.dldir = self.sstatedir = self.sstatemirror = ""
- self.pmake = self.bbthread = 0
- self.curr_package_format = ""
- self.image_rootfs_size = self.image_extra_size = 0
- self.image_overhead_factor = 1
- self.incompat_license = ""
- self.curr_sdk_machine = ""
- self.conf_version = self.lconf_version = ""
- self.extra_setting = {}
- self.toolchain_build = False
- self.image_fstypes = ""
- self.image_size = None
- self.image_packages = []
- # bblayers.conf
- self.layers = []
- # image/recipes/packages
- self.clear_selection()
-
- self.user_selected_packages = []
-
- self.default_task = "build"
-
- # proxy settings
- self.enable_proxy = None
- self.same_proxy = False
- self.proxies = {
- "http" : [None, None, None, "", ""], # protocol : [prot, user, passwd, host, port]
- "https" : [None, None, None, "", ""],
- "ftp" : [None, None, None, "", ""],
- "socks" : [None, None, None, "", ""],
- "cvs" : [None, None, None, "", ""],
- }
-
- def clear_selection(self):
- self.selected_recipes = []
- self.selected_packages = []
- self.initial_selected_image = None
- self.initial_selected_packages = []
- self.initial_user_selected_packages = []
-
- def split_proxy(self, protocol, proxy):
- entry = []
- prot, user, passwd, host, port = Configuration.parse_proxy_string(proxy)
- entry.append(prot)
- entry.append(user)
- entry.append(passwd)
- entry.append(host)
- entry.append(port)
- self.proxies[protocol] = entry
-
- def combine_proxy(self, protocol):
- entry = self.proxies[protocol]
- return Configuration.make_proxy_string(entry[0], entry[1], entry[2], entry[3], entry[4], protocol)
-
- def combine_host_only(self, protocol):
- entry = self.proxies[protocol]
- return Configuration.make_host_string(entry[0], entry[1], entry[2], entry[3], protocol)
-
- def combine_port_only(self, protocol):
- entry = self.proxies[protocol]
- return Configuration.make_port_string(entry[4])
-
- def update(self, params):
- # settings
- self.curr_distro = params["distro"]
- self.dldir = params["dldir"]
- self.sstatedir = params["sstatedir"]
- self.sstatemirror = params["sstatemirror"]
- self.pmake = int(params["pmake"].split()[1])
- self.bbthread = params["bbthread"]
- self.curr_package_format = " ".join(params["pclass"].split("package_")).strip()
- self.image_rootfs_size = params["image_rootfs_size"]
- self.image_extra_size = params["image_extra_size"]
- self.image_overhead_factor = params['image_overhead_factor']
- self.incompat_license = params["incompat_license"]
- self.curr_sdk_machine = params["sdk_machine"]
- self.conf_version = params["conf_version"]
- self.lconf_version = params["lconf_version"]
- self.image_fstypes = params["image_fstypes"]
- # self.extra_setting/self.toolchain_build
- # bblayers.conf
- self.layers = params["layer"].split()
- self.layers_non_removable = params["layers_non_removable"].split()
- self.default_task = params["default_task"]
-
- # proxy settings
- self.enable_proxy = params["http_proxy"] != "" or params["https_proxy"] != "" \
- or params["ftp_proxy"] != "" or params["socks_proxy"] != "" \
- or params["cvs_proxy_host"] != "" or params["cvs_proxy_port"] != ""
- self.split_proxy("http", params["http_proxy"])
- self.split_proxy("https", params["https_proxy"])
- self.split_proxy("ftp", params["ftp_proxy"])
- self.split_proxy("socks", params["socks_proxy"])
- self.split_proxy("cvs", params["cvs_proxy_host"] + ":" + params["cvs_proxy_port"])
-
- def save(self, handler, defaults=False):
- # bblayers.conf
- handler.set_var_in_file("BBLAYERS", self.layers, "bblayers.conf")
- # local.conf
- if not defaults:
- handler.early_assign_var_in_file("MACHINE", self.curr_mach, "local.conf")
- handler.set_var_in_file("DISTRO", self.curr_distro, "local.conf")
- handler.set_var_in_file("DL_DIR", self.dldir, "local.conf")
- handler.set_var_in_file("SSTATE_DIR", self.sstatedir, "local.conf")
- sstate_mirror_list = self.sstatemirror.split("\\n ")
- sstate_mirror_list_modified = []
- for mirror in sstate_mirror_list:
- if mirror != "":
- mirror = mirror + "\\n"
- sstate_mirror_list_modified.append(mirror)
- handler.set_var_in_file("SSTATE_MIRRORS", sstate_mirror_list_modified, "local.conf")
- handler.set_var_in_file("PARALLEL_MAKE", "-j %s" % self.pmake, "local.conf")
- handler.set_var_in_file("BB_NUMBER_THREADS", self.bbthread, "local.conf")
- handler.set_var_in_file("PACKAGE_CLASSES", " ".join(["package_" + i for i in self.curr_package_format.split()]), "local.conf")
- handler.set_var_in_file("IMAGE_ROOTFS_SIZE", self.image_rootfs_size, "local.conf")
- handler.set_var_in_file("IMAGE_EXTRA_SPACE", self.image_extra_size, "local.conf")
- handler.set_var_in_file("INCOMPATIBLE_LICENSE", self.incompat_license, "local.conf")
- handler.set_var_in_file("SDKMACHINE", self.curr_sdk_machine, "local.conf")
- handler.set_var_in_file("CONF_VERSION", self.conf_version, "local.conf")
- handler.set_var_in_file("LCONF_VERSION", self.lconf_version, "bblayers.conf")
- handler.set_extra_config(self.extra_setting)
- handler.set_var_in_file("TOOLCHAIN_BUILD", self.toolchain_build, "local.conf")
- handler.set_var_in_file("IMAGE_FSTYPES", self.image_fstypes, "local.conf")
- if not defaults:
- # image/recipes/packages
- handler.set_var_in_file("__SELECTED_IMAGE__", self.selected_image, "local.conf")
- handler.set_var_in_file("DEPENDS", self.selected_recipes, "local.conf")
- handler.set_var_in_file("IMAGE_INSTALL", self.user_selected_packages, "local.conf")
- # proxy
- if self.enable_proxy == True:
- handler.set_var_in_file("http_proxy", self.combine_proxy("http"), "local.conf")
- handler.set_var_in_file("https_proxy", self.combine_proxy("https"), "local.conf")
- handler.set_var_in_file("ftp_proxy", self.combine_proxy("ftp"), "local.conf")
- handler.set_var_in_file("all_proxy", self.combine_proxy("socks"), "local.conf")
- handler.set_var_in_file("CVS_PROXY_HOST", self.combine_host_only("cvs"), "local.conf")
- handler.set_var_in_file("CVS_PROXY_PORT", self.combine_port_only("cvs"), "local.conf")
- else:
- handler.set_var_in_file("http_proxy", "", "local.conf")
- handler.set_var_in_file("https_proxy", "", "local.conf")
- handler.set_var_in_file("ftp_proxy", "", "local.conf")
- handler.set_var_in_file("all_proxy", "", "local.conf")
- handler.set_var_in_file("CVS_PROXY_HOST", "", "local.conf")
- handler.set_var_in_file("CVS_PROXY_PORT", "", "local.conf")
-
- def __str__(self):
- s = "VERSION: '%s', BBLAYERS: '%s', MACHINE: '%s', DISTRO: '%s', DL_DIR: '%s'," % \
- (hobVer, " ".join(self.layers), self.curr_mach, self.curr_distro, self.dldir )
- s += "SSTATE_DIR: '%s', SSTATE_MIRROR: '%s', PARALLEL_MAKE: '-j %s', BB_NUMBER_THREADS: '%s', PACKAGE_CLASSES: '%s', " % \
- (self.sstatedir, self.sstatemirror, self.pmake, self.bbthread, " ".join(["package_" + i for i in self.curr_package_format.split()]))
- s += "IMAGE_ROOTFS_SIZE: '%s', IMAGE_EXTRA_SPACE: '%s', INCOMPATIBLE_LICENSE: '%s', SDKMACHINE: '%s', CONF_VERSION: '%s', " % \
- (self.image_rootfs_size, self.image_extra_size, self.incompat_license, self.curr_sdk_machine, self.conf_version)
- s += "LCONF_VERSION: '%s', EXTRA_SETTING: '%s', TOOLCHAIN_BUILD: '%s', IMAGE_FSTYPES: '%s', __SELECTED_IMAGE__: '%s', " % \
- (self.lconf_version, self.extra_setting, self.toolchain_build, self.image_fstypes, self.selected_image)
- s += "DEPENDS: '%s', IMAGE_INSTALL: '%s', enable_proxy: '%s', use_same_proxy: '%s', http_proxy: '%s', " % \
- (self.selected_recipes, self.user_selected_packages, self.enable_proxy, self.same_proxy, self.combine_proxy("http"))
- s += "https_proxy: '%s', ftp_proxy: '%s', all_proxy: '%s', CVS_PROXY_HOST: '%s', CVS_PROXY_PORT: '%s'" % \
- (self.combine_proxy("https"), self.combine_proxy("ftp"), self.combine_proxy("socks"),
- self.combine_host_only("cvs"), self.combine_port_only("cvs"))
- return s
-
-class Parameters:
- '''Represents other variables like available machines, etc.'''
-
- def __init__(self):
- # Variables
- self.max_threads = 65535
- self.core_base = ""
- self.image_addr = ""
- self.image_types = []
- self.runnable_image_types = []
- self.runnable_machine_patterns = []
- self.deployable_image_types = []
- self.tmpdir = ""
-
- self.all_machines = []
- self.all_package_formats = []
- self.all_distros = []
- self.all_sdk_machines = []
- self.all_layers = []
- self.image_names = []
- self.image_white_pattern = ""
- self.image_black_pattern = ""
-
- # for build log to show
- self.bb_version = ""
- self.target_arch = ""
- self.target_os = ""
- self.distro_version = ""
- self.tune_pkgarch = ""
-
- def update(self, params):
- self.max_threads = params["max_threads"]
- self.core_base = params["core_base"]
- self.image_addr = params["image_addr"]
- self.image_types = params["image_types"].split()
- self.runnable_image_types = params["runnable_image_types"].split()
- self.runnable_machine_patterns = params["runnable_machine_patterns"].split()
- self.deployable_image_types = params["deployable_image_types"].split()
- self.tmpdir = params["tmpdir"]
- self.image_white_pattern = params["image_white_pattern"]
- self.image_black_pattern = params["image_black_pattern"]
- self.kernel_image_type = params["kernel_image_type"]
- # for build log to show
- self.bb_version = params["bb_version"]
- self.target_arch = params["target_arch"]
- self.target_os = params["target_os"]
- self.distro_version = params["distro_version"]
- self.tune_pkgarch = params["tune_pkgarch"]
-
-def hob_conf_filter(fn, data):
- if fn.endswith("/local.conf"):
- distro = data.getVar("DISTRO_HOB", False)
- if distro:
- if distro != "defaultsetup":
- data.setVar("DISTRO", distro)
- else:
- data.delVar("DISTRO")
-
- keys = ["MACHINE_HOB", "SDKMACHINE_HOB", "PACKAGE_CLASSES_HOB", \
- "BB_NUMBER_THREADS_HOB", "PARALLEL_MAKE_HOB", "DL_DIR_HOB", \
- "SSTATE_DIR_HOB", "SSTATE_MIRRORS_HOB", "INCOMPATIBLE_LICENSE_HOB"]
- for key in keys:
- var_hob = data.getVar(key, False)
- if var_hob:
- data.setVar(key.split("_HOB")[0], var_hob)
- return
-
- if fn.endswith("/bblayers.conf"):
- layers = data.getVar("BBLAYERS_HOB", False)
- if layers:
- data.setVar("BBLAYERS", layers)
- return
-
-class Builder(gtk.Window):
-
- (INITIAL_CHECKS,
- MACHINE_SELECTION,
- RCPPKGINFO_POPULATING,
- RCPPKGINFO_POPULATED,
- BASEIMG_SELECTED,
- RECIPE_SELECTION,
- PACKAGE_GENERATING,
- PACKAGE_GENERATED,
- PACKAGE_SELECTION,
- FAST_IMAGE_GENERATING,
- IMAGE_GENERATING,
- IMAGE_GENERATED,
- MY_IMAGE_OPENED,
- BACK,
- END_NOOP) = range(15)
-
- (SANITY_CHECK,
- IMAGE_CONFIGURATION,
- RECIPE_DETAILS,
- BUILD_DETAILS,
- PACKAGE_DETAILS,
- IMAGE_DETAILS,
- END_TAB) = range(7)
-
- __step2page__ = {
- INITIAL_CHECKS : SANITY_CHECK,
- MACHINE_SELECTION : IMAGE_CONFIGURATION,
- RCPPKGINFO_POPULATING : IMAGE_CONFIGURATION,
- RCPPKGINFO_POPULATED : IMAGE_CONFIGURATION,
- BASEIMG_SELECTED : IMAGE_CONFIGURATION,
- RECIPE_SELECTION : RECIPE_DETAILS,
- PACKAGE_GENERATING : BUILD_DETAILS,
- PACKAGE_GENERATED : PACKAGE_DETAILS,
- PACKAGE_SELECTION : PACKAGE_DETAILS,
- FAST_IMAGE_GENERATING : BUILD_DETAILS,
- IMAGE_GENERATING : BUILD_DETAILS,
- IMAGE_GENERATED : IMAGE_DETAILS,
- MY_IMAGE_OPENED : IMAGE_DETAILS,
- END_NOOP : None,
- }
-
- SANITY_CHECK_MIN_DISPLAY_TIME = 5
-
- def __init__(self, hobHandler, recipe_model, package_model):
- super(Builder, self).__init__()
-
- self.hob_image = "hob-image"
-
- # handler
- self.handler = hobHandler
-
- # logger
- self.logger = logging.getLogger("BitBake")
- self.consolelog = None
- self.current_logfile = None
-
- # configuration and parameters
- self.configuration = Configuration()
- self.parameters = Parameters()
-
- # build step
- self.current_step = None
- self.previous_step = None
-
- self.stopping = False
-
- # recipe model and package model
- self.recipe_model = recipe_model
- self.package_model = package_model
-
- # Indicate whether user has customized the image
- self.customized = False
-
- # Indicate whether the UI is working
- self.sensitive = True
-
- # Indicate whether the sanity check ran
- self.sanity_checked = False
-
- # save parsing warnings
- self.parsing_warnings = []
-
- # create visual elements
- self.create_visual_elements()
-
- # connect the signals to functions
- self.connect("delete-event", self.destroy_window_cb)
- self.recipe_model.connect ("recipe-selection-changed", self.recipelist_changed_cb)
- self.package_model.connect("package-selection-changed", self.packagelist_changed_cb)
- self.handler.connect("config-updated", self.handler_config_updated_cb)
- self.handler.connect("package-formats-updated", self.handler_package_formats_updated_cb)
- self.handler.connect("parsing-started", self.handler_parsing_started_cb)
- self.handler.connect("parsing", self.handler_parsing_cb)
- self.handler.connect("parsing-completed", self.handler_parsing_completed_cb)
- self.handler.build.connect("build-started", self.handler_build_started_cb)
- self.handler.build.connect("build-succeeded", self.handler_build_succeeded_cb)
- self.handler.build.connect("build-failed", self.handler_build_failed_cb)
- self.handler.build.connect("build-aborted", self.handler_build_aborted_cb)
- self.handler.build.connect("task-started", self.handler_task_started_cb)
- self.handler.build.connect("disk-full", self.handler_disk_full_cb)
- self.handler.build.connect("log-error", self.handler_build_failure_cb)
- self.handler.build.connect("log-warning", self.handler_build_failure_cb)
- self.handler.build.connect("log", self.handler_build_log_cb)
- self.handler.build.connect("no-provider", self.handler_no_provider_cb)
- self.handler.connect("generating-data", self.handler_generating_data_cb)
- self.handler.connect("data-generated", self.handler_data_generated_cb)
- self.handler.connect("command-succeeded", self.handler_command_succeeded_cb)
- self.handler.connect("command-failed", self.handler_command_failed_cb)
- self.handler.connect("parsing-warning", self.handler_parsing_warning_cb)
- self.handler.connect("sanity-failed", self.handler_sanity_failed_cb)
- self.handler.connect("recipe-populated", self.handler_recipe_populated_cb)
- self.handler.connect("package-populated", self.handler_package_populated_cb)
-
- self.handler.append_to_bbfiles("${TOPDIR}/recipes/images/custom/*.bb")
- self.handler.append_to_bbfiles("${TOPDIR}/recipes/images/*.bb")
- self.initiate_new_build_async()
-
- signal.signal(signal.SIGINT, self.event_handle_SIGINT)
-
- def create_visual_elements(self):
- self.set_title("Hob")
- self.set_icon_name("applications-development")
- self.set_resizable(True)
-
- try:
- window_width = self.get_screen().get_width()
- window_height = self.get_screen().get_height()
- except AttributeError:
- print "Please set DISPLAY variable before running Hob."
- sys.exit(1)
-
- if window_width >= hwc.MAIN_WIN_WIDTH:
- window_width = hwc.MAIN_WIN_WIDTH
- window_height = hwc.MAIN_WIN_HEIGHT
- self.set_size_request(window_width, window_height)
-
- self.vbox = gtk.VBox(False, 0)
- self.vbox.set_border_width(0)
- self.add(self.vbox)
-
- # create pages
- self.image_configuration_page = ImageConfigurationPage(self)
- self.recipe_details_page = RecipeSelectionPage(self)
- self.build_details_page = BuildDetailsPage(self)
- self.package_details_page = PackageSelectionPage(self)
- self.image_details_page = ImageDetailsPage(self)
- self.sanity_check_page = SanityCheckPage(self)
- self.display_sanity_check = False
- self.sanity_check_post_func = False
- self.had_network_error = False
-
- self.nb = gtk.Notebook()
- self.nb.set_show_tabs(False)
- self.nb.insert_page(self.sanity_check_page, None, self.SANITY_CHECK)
- self.nb.insert_page(self.image_configuration_page, None, self.IMAGE_CONFIGURATION)
- self.nb.insert_page(self.recipe_details_page, None, self.RECIPE_DETAILS)
- self.nb.insert_page(self.build_details_page, None, self.BUILD_DETAILS)
- self.nb.insert_page(self.package_details_page, None, self.PACKAGE_DETAILS)
- self.nb.insert_page(self.image_details_page, None, self.IMAGE_DETAILS)
- self.vbox.pack_start(self.nb, expand=True, fill=True)
-
- self.show_all()
- self.nb.set_current_page(0)
-
- def sanity_check_timeout(self):
- # The minimum time for showing the 'sanity check' page has passe
- # If someone set the 'sanity_check_post_step' meanwhile, execute it now
- self.display_sanity_check = False
- if self.sanity_check_post_func:
- temp = self.sanity_check_post_func
- self.sanity_check_post_func = None
- temp()
- return False
-
- def show_sanity_check_page(self):
- # This window must stay on screen for at least 5 seconds, according to the design document
- self.nb.set_current_page(self.SANITY_CHECK)
- self.sanity_check_post_step = None
- self.display_sanity_check = True
- self.sanity_check_page.start()
- gobject.timeout_add(self.SANITY_CHECK_MIN_DISPLAY_TIME * 1000, self.sanity_check_timeout)
-
- def execute_after_sanity_check(self, func):
- if not self.display_sanity_check:
- func()
- else:
- self.sanity_check_post_func = func
-
- def generate_configuration(self):
- if not self.sanity_checked:
- self.show_sanity_check_page()
- self.handler.generate_configuration()
-
- def initiate_new_build_async(self):
- self.configuration.selected_image = None
- self.switch_page(self.MACHINE_SELECTION)
- self.handler.init_cooker()
- self.handler.set_extra_inherit("image_types")
- self.generate_configuration()
-
- def update_config_async(self):
- self.set_user_config()
- self.generate_configuration()
- self.switch_page(self.MACHINE_SELECTION)
-
- def sanity_check(self):
- self.handler.trigger_sanity_check()
-
- def populate_recipe_package_info_async(self):
- self.switch_page(self.RCPPKGINFO_POPULATING)
- # Parse recipes
- self.set_user_config()
- self.handler.generate_recipes()
-
- def generate_packages_async(self, log = False):
- self.switch_page(self.PACKAGE_GENERATING)
- if log:
- self.current_logfile = self.handler.get_logfile()
- self.do_log(self.current_logfile)
- # Build packages
- _, all_recipes = self.recipe_model.get_selected_recipes()
- self.set_user_config()
- self.handler.reset_build()
- self.handler.generate_packages(all_recipes, self.configuration.default_task)
-
- def restore_initial_selected_packages(self):
- self.package_model.set_selected_packages(self.configuration.initial_user_selected_packages, True)
- self.package_model.set_selected_packages(self.configuration.initial_selected_packages)
- for package in self.configuration.selected_packages:
- if package not in self.configuration.initial_selected_packages:
- self.package_model.exclude_item(self.package_model.find_path_for_item(package))
-
- def fast_generate_image_async(self, log = False):
- self.switch_page(self.FAST_IMAGE_GENERATING)
- if log:
- self.current_logfile = self.handler.get_logfile()
- self.do_log(self.current_logfile)
- # Build packages
- _, all_recipes = self.recipe_model.get_selected_recipes()
- self.set_user_config()
- self.handler.reset_build()
- self.handler.generate_packages(all_recipes, self.configuration.default_task)
-
- def generate_image_async(self, cont = False):
- self.switch_page(self.IMAGE_GENERATING)
- self.handler.reset_build()
- if not cont:
- self.current_logfile = self.handler.get_logfile()
- self.do_log(self.current_logfile)
- # Build image
- self.set_user_config()
- toolchain_packages = []
- base_image = None
- if self.configuration.toolchain_build:
- toolchain_packages = self.package_model.get_selected_packages_toolchain()
- if self.configuration.selected_image == self.recipe_model.__custom_image__:
- packages = self.package_model.get_selected_packages()
- image = self.hob_image
- base_image = self.configuration.initial_selected_image
- else:
- packages = []
- image = self.configuration.selected_image
- self.handler.generate_image(image,
- base_image,
- packages,
- toolchain_packages,
- self.configuration.default_task)
-
- def generate_new_image(self, image, description):
- base_image = self.configuration.initial_selected_image
- if base_image == self.recipe_model.__custom_image__:
- base_image = None
- packages = self.package_model.get_selected_packages()
- self.handler.generate_new_image(image, base_image, packages, description)
-
- def ensure_dir(self, directory):
- self.handler.ensure_dir(directory)
-
- def get_parameters_sync(self):
- return self.handler.get_parameters()
-
- def request_package_info_async(self):
- self.handler.request_package_info()
-
- def cancel_build_sync(self, force=False):
- self.handler.cancel_build(force)
-
- def cancel_parse_sync(self):
- self.handler.cancel_parse()
-
- def switch_page(self, next_step):
- # Main Workflow (Business Logic)
- self.nb.set_current_page(self.__step2page__[next_step])
-
- if next_step == self.MACHINE_SELECTION: # init step
- self.image_configuration_page.show_machine()
-
- elif next_step == self.RCPPKGINFO_POPULATING:
- # MACHINE CHANGED action or SETTINGS CHANGED
- # show the progress bar
- self.image_configuration_page.show_info_populating()
-
- elif next_step == self.RCPPKGINFO_POPULATED:
- self.image_configuration_page.show_info_populated()
-
- elif next_step == self.BASEIMG_SELECTED:
- self.image_configuration_page.show_baseimg_selected()
-
- elif next_step == self.RECIPE_SELECTION:
- if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
- self.recipe_details_page.set_recipe_curr_tab(self.recipe_details_page.ALL)
- else:
- self.recipe_details_page.set_recipe_curr_tab(self.recipe_details_page.INCLUDED)
-
- elif next_step == self.PACKAGE_SELECTION:
- self.configuration.initial_selected_packages = self.configuration.selected_packages
- self.configuration.initial_user_selected_packages = self.configuration.user_selected_packages
- self.package_details_page.set_title("Edit packages")
- if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
- self.package_details_page.set_packages_curr_tab(self.package_details_page.ALL)
- else:
- self.package_details_page.set_packages_curr_tab(self.package_details_page.INCLUDED)
- self.package_details_page.show_page(self.current_logfile)
-
-
- elif next_step == self.PACKAGE_GENERATING or next_step == self.FAST_IMAGE_GENERATING:
- # both PACKAGE_GENERATING and FAST_IMAGE_GENERATING share the same page
- self.build_details_page.show_page(next_step)
-
- elif next_step == self.PACKAGE_GENERATED:
- self.package_details_page.set_title("Step 2 of 2: Edit packages")
- if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
- self.package_details_page.set_packages_curr_tab(self.package_details_page.ALL)
- else:
- self.package_details_page.set_packages_curr_tab(self.package_details_page.INCLUDED)
- self.package_details_page.show_page(self.current_logfile)
-
- elif next_step == self.IMAGE_GENERATING:
- # after packages are generated, selected_packages need to
- # be updated in package_model per selected_image in recipe_model
- self.build_details_page.show_page(next_step)
-
- elif next_step == self.IMAGE_GENERATED:
- self.image_details_page.show_page(next_step)
-
- elif next_step == self.MY_IMAGE_OPENED:
- self.image_details_page.show_page(next_step)
-
- self.previous_step = self.current_step
- self.current_step = next_step
-
- def set_user_config_proxies(self):
- if self.configuration.enable_proxy == True:
- self.handler.set_http_proxy(self.configuration.combine_proxy("http"))
- self.handler.set_https_proxy(self.configuration.combine_proxy("https"))
- self.handler.set_ftp_proxy(self.configuration.combine_proxy("ftp"))
- self.handler.set_socks_proxy(self.configuration.combine_proxy("socks"))
- self.handler.set_cvs_proxy(self.configuration.combine_host_only("cvs"), self.configuration.combine_port_only("cvs"))
- elif self.configuration.enable_proxy == False:
- self.handler.set_http_proxy("")
- self.handler.set_https_proxy("")
- self.handler.set_ftp_proxy("")
- self.handler.set_socks_proxy("")
- self.handler.set_cvs_proxy("", "")
-
- def set_user_config_extra(self):
- self.handler.set_rootfs_size(self.configuration.image_rootfs_size)
- self.handler.set_extra_size(self.configuration.image_extra_size)
- self.handler.set_incompatible_license(self.configuration.incompat_license)
- self.handler.set_sdk_machine(self.configuration.curr_sdk_machine)
- self.handler.set_image_fstypes(self.configuration.image_fstypes)
- self.handler.set_extra_config(self.configuration.extra_setting)
- self.handler.set_extra_inherit("packageinfo image_types")
- self.set_user_config_proxies()
-
- def set_user_config(self):
- # set bb layers
- self.handler.set_bblayers(self.configuration.layers)
- # set local configuration
- self.handler.set_machine(self.configuration.curr_mach)
- self.handler.set_package_format(self.configuration.curr_package_format)
- self.handler.set_distro(self.configuration.curr_distro)
- self.handler.set_dl_dir(self.configuration.dldir)
- self.handler.set_sstate_dir(self.configuration.sstatedir)
- self.handler.set_sstate_mirrors(self.configuration.sstatemirror)
- self.handler.set_pmake(self.configuration.pmake)
- self.handler.set_bbthreads(self.configuration.bbthread)
- self.set_user_config_extra()
-
- def update_recipe_model(self, selected_image, selected_recipes):
- self.recipe_model.set_selected_image(selected_image)
- self.recipe_model.set_selected_recipes(selected_recipes)
-
- def update_package_model(self, selected_packages, user_selected_packages=None):
- if user_selected_packages:
- left = self.package_model.set_selected_packages(user_selected_packages, True)
- self.configuration.user_selected_packages += left
- left = self.package_model.set_selected_packages(selected_packages)
- self.configuration.selected_packages += left
-
- def update_configuration_parameters(self, params):
- if params:
- self.configuration.update(params)
- self.parameters.update(params)
-
- def set_base_image(self):
- self.configuration.initial_selected_image = self.configuration.selected_image
- if self.configuration.selected_image != self.recipe_model.__custom_image__:
- self.hob_image = self.configuration.selected_image + "-edited"
-
- def reset(self):
- self.configuration.curr_mach = ""
- self.configuration.clear_selection()
- self.image_configuration_page.switch_machine_combo()
- self.switch_page(self.MACHINE_SELECTION)
-
- # Callback Functions
- def handler_config_updated_cb(self, handler, which, values):
- if which == "distro":
- self.parameters.all_distros = values
- elif which == "machine":
- self.parameters.all_machines = values
- self.image_configuration_page.update_machine_combo()
- elif which == "machine-sdk":
- self.parameters.all_sdk_machines = values
-
- def handler_package_formats_updated_cb(self, handler, formats):
- self.parameters.all_package_formats = formats
-
- def switch_to_image_configuration_helper(self):
- self.sanity_check_page.stop()
- self.switch_page(self.IMAGE_CONFIGURATION)
- self.image_configuration_page.switch_machine_combo()
-
- def show_network_error_dialog_helper(self):
- self.sanity_check_page.stop()
- self.show_network_error_dialog()
-
- def handler_command_succeeded_cb(self, handler, initcmd):
- if initcmd == self.handler.GENERATE_CONFIGURATION:
- if not self.configuration.curr_mach:
- self.configuration.curr_mach = self.handler.runCommand(["getVariable", "HOB_MACHINE"]) or ""
- self.update_configuration_parameters(self.get_parameters_sync())
- if not self.sanity_checked:
- self.sanity_check()
- self.sanity_checked = True
- elif initcmd == self.handler.SANITY_CHECK:
- if self.had_network_error:
- self.had_network_error = False
- self.execute_after_sanity_check(self.show_network_error_dialog_helper)
- else:
- # Switch to the 'image configuration' page now, but we might need
- # to wait for the minimum display time of the sanity check page
- self.execute_after_sanity_check(self.switch_to_image_configuration_helper)
- elif initcmd in [self.handler.GENERATE_RECIPES,
- self.handler.GENERATE_PACKAGES,
- self.handler.GENERATE_IMAGE]:
- self.update_configuration_parameters(self.get_parameters_sync())
- self.request_package_info_async()
- elif initcmd == self.handler.POPULATE_PACKAGEINFO:
- if self.current_step == self.RCPPKGINFO_POPULATING:
- self.switch_page(self.RCPPKGINFO_POPULATED)
- self.rcppkglist_populated()
- return
-
- self.rcppkglist_populated()
- if self.current_step == self.FAST_IMAGE_GENERATING:
- self.generate_image_async(True)
-
- def show_error_dialog(self, msg):
- lbl = "<b>Hob found an error</b>"
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_ERROR, msg)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- response = dialog.run()
- dialog.destroy()
-
- def show_warning_dialog(self):
- dialog = ParsingWarningsDialog(title = "View warnings",
- warnings = self.parsing_warnings,
- parent = None,
- flags = gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR)
- response = dialog.run()
- dialog.destroy()
-
- def show_network_error_dialog(self):
- lbl = "<b>Hob cannot connect to the network</b>"
- msg = msg + "Please check your network connection. If you are using a proxy server, please make sure it is configured correctly."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_ERROR, msg)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- button = dialog.add_button("Proxy settings", gtk.RESPONSE_CANCEL)
- HobButton.style_button(button)
- res = dialog.run()
- dialog.destroy()
- if res == gtk.RESPONSE_CANCEL:
- res, settings_changed = self.show_simple_settings_dialog(SimpleSettingsDialog.PROXIES_PAGE_ID)
- if not res:
- return
- if settings_changed:
- self.reparse_post_adv_settings()
-
- def handler_command_failed_cb(self, handler, msg):
- if msg:
- self.show_error_dialog(msg)
- self.reset()
-
- def handler_parsing_warning_cb(self, handler, warn_msg):
- self.parsing_warnings.append(warn_msg)
-
- def handler_sanity_failed_cb(self, handler, msg, network_error):
- self.reset()
- if network_error:
- # Mark this in an internal field. The "network error" dialog will be
- # shown later, when a SanityCheckPassed event will be handled
- # (as sent by sanity.bbclass)
- self.had_network_error = True
- else:
- msg = msg.replace("your local.conf", "Settings")
- self.show_error_dialog(msg)
- self.reset()
-
- def window_sensitive(self, sensitive):
- self.image_configuration_page.machine_combo.set_sensitive(sensitive)
- self.image_configuration_page.machine_combo.child.set_sensitive(sensitive)
- self.image_configuration_page.image_combo.set_sensitive(sensitive)
- self.image_configuration_page.image_combo.child.set_sensitive(sensitive)
- self.image_configuration_page.layer_button.set_sensitive(sensitive)
- self.image_configuration_page.layer_info_icon.set_sensitive(sensitive)
- self.image_configuration_page.toolbar.set_sensitive(sensitive)
- self.image_configuration_page.view_adv_configuration_button.set_sensitive(sensitive)
- self.image_configuration_page.config_build_button.set_sensitive(sensitive)
-
- self.recipe_details_page.set_sensitive(sensitive)
- self.package_details_page.set_sensitive(sensitive)
- self.build_details_page.set_sensitive(sensitive)
- self.image_details_page.set_sensitive(sensitive)
-
- if sensitive:
- self.window.set_cursor(None)
- else:
- self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
- self.sensitive = sensitive
-
-
- def handler_generating_data_cb(self, handler):
- self.window_sensitive(False)
-
- def handler_data_generated_cb(self, handler):
- self.window_sensitive(True)
-
- def rcppkglist_populated(self):
- selected_image = self.configuration.selected_image
- selected_recipes = self.configuration.selected_recipes[:]
- selected_packages = self.configuration.selected_packages[:]
- user_selected_packages = self.configuration.user_selected_packages[:]
-
- self.image_configuration_page.update_image_combo(self.recipe_model, selected_image)
- self.image_configuration_page.update_image_desc()
- self.update_recipe_model(selected_image, selected_recipes)
- self.update_package_model(selected_packages, user_selected_packages)
-
- def recipelist_changed_cb(self, recipe_model):
- self.recipe_details_page.refresh_selection()
-
- def packagelist_changed_cb(self, package_model):
- self.package_details_page.refresh_selection()
-
- def handler_recipe_populated_cb(self, handler):
- self.image_configuration_page.update_progress_bar("Populating recipes", 0.99)
-
- def handler_package_populated_cb(self, handler):
- self.image_configuration_page.update_progress_bar("Populating packages", 1.0)
-
- def handler_parsing_started_cb(self, handler, message):
- if self.current_step != self.RCPPKGINFO_POPULATING:
- return
-
- fraction = 0
- if message["eventname"] == "TreeDataPreparationStarted":
- fraction = 0.6 + fraction
- self.image_configuration_page.stop_button.set_sensitive(False)
- self.image_configuration_page.update_progress_bar("Generating dependency tree", fraction)
- else:
- self.image_configuration_page.stop_button.set_sensitive(True)
- self.image_configuration_page.update_progress_bar(message["title"], fraction)
-
- def handler_parsing_cb(self, handler, message):
- if self.current_step != self.RCPPKGINFO_POPULATING:
- return
-
- fraction = message["current"] * 1.0/message["total"]
- if message["eventname"] == "TreeDataPreparationProgress":
- fraction = 0.6 + 0.38 * fraction
- self.image_configuration_page.update_progress_bar("Generating dependency tree", fraction)
- else:
- fraction = 0.6 * fraction
- self.image_configuration_page.update_progress_bar(message["title"], fraction)
-
- def handler_parsing_completed_cb(self, handler, message):
- if self.current_step != self.RCPPKGINFO_POPULATING:
- return
-
- if message["eventname"] == "TreeDataPreparationCompleted":
- fraction = 0.98
- else:
- fraction = 0.6
- self.image_configuration_page.update_progress_bar("Generating dependency tree", fraction)
-
- def handler_build_started_cb(self, running_build):
- if self.current_step == self.FAST_IMAGE_GENERATING:
- fraction = 0
- elif self.current_step == self.IMAGE_GENERATING:
- if self.previous_step == self.FAST_IMAGE_GENERATING:
- fraction = 0.9
- else:
- fraction = 0
- elif self.current_step == self.PACKAGE_GENERATING:
- fraction = 0
- self.build_details_page.update_progress_bar("Build Started: ", fraction)
- self.build_details_page.show_configurations(self.configuration, self.parameters)
-
- def build_succeeded(self):
- if self.current_step == self.FAST_IMAGE_GENERATING:
- fraction = 0.9
- elif self.current_step == self.IMAGE_GENERATING:
- fraction = 1.0
- version = ""
- self.parameters.image_names = []
- selected_image = self.recipe_model.get_selected_image()
- if selected_image == self.recipe_model.__custom_image__:
- if self.configuration.initial_selected_image != selected_image:
- version = self.recipe_model.get_custom_image_version()
- linkname = self.hob_image + version + "-" + self.configuration.curr_mach
- else:
- linkname = selected_image + '-' + self.configuration.curr_mach
- image_extension = self.get_image_extension()
- for image_type in self.parameters.image_types:
- if image_type in image_extension:
- real_types = image_extension[image_type]
- else:
- real_types = [image_type]
- for real_image_type in real_types:
- linkpath = self.parameters.image_addr + '/' + linkname + '.' + real_image_type
- if os.path.exists(linkpath):
- self.parameters.image_names.append(os.readlink(linkpath))
- elif self.current_step == self.PACKAGE_GENERATING:
- fraction = 1.0
- self.build_details_page.update_progress_bar("Build Completed: ", fraction)
- self.handler.build_succeeded_async()
- self.stopping = False
-
- if self.current_step == self.PACKAGE_GENERATING:
- self.switch_page(self.PACKAGE_GENERATED)
- elif self.current_step == self.IMAGE_GENERATING:
- self.switch_page(self.IMAGE_GENERATED)
-
- def build_failed(self):
- if self.stopping:
- status = "stop"
- message = "Build stopped: "
- fraction = self.build_details_page.progress_bar.get_fraction()
- stop_to_next_edit = ""
- if self.current_step == self.FAST_IMAGE_GENERATING:
- stop_to_next_edit = "image configuration"
- elif self.current_step == self.IMAGE_GENERATING:
- if self.previous_step == self.FAST_IMAGE_GENERATING:
- stop_to_next_edit = "image configuration"
- else:
- stop_to_next_edit = "packages"
- elif self.current_step == self.PACKAGE_GENERATING:
- stop_to_next_edit = "recipes"
- button = self.build_details_page.show_stop_page(stop_to_next_edit.split(' ')[0])
- self.set_default(button)
- else:
- fail_to_next_edit = ""
- if self.current_step == self.FAST_IMAGE_GENERATING:
- fail_to_next_edit = "image configuration"
- fraction = 0.9
- elif self.current_step == self.IMAGE_GENERATING:
- if self.previous_step == self.FAST_IMAGE_GENERATING:
- fail_to_next_edit = "image configuration"
- else:
- fail_to_next_edit = "packages"
- fraction = 1.0
- elif self.current_step == self.PACKAGE_GENERATING:
- fail_to_next_edit = "recipes"
- fraction = 1.0
- self.build_details_page.show_fail_page(fail_to_next_edit.split(' ')[0])
- status = "fail"
- message = "Build failed: "
- self.build_details_page.update_progress_bar(message, fraction, status)
- self.build_details_page.show_back_button()
- self.build_details_page.hide_stop_button()
- self.handler.build_failed_async()
- self.stopping = False
-
- def handler_build_succeeded_cb(self, running_build):
- if not self.stopping:
- self.build_succeeded()
- else:
- self.build_failed()
-
-
- def handler_build_failed_cb(self, running_build):
- self.build_failed()
-
- def handler_build_aborted_cb(self, running_build):
- self.build_failed()
-
- def handler_no_provider_cb(self, running_build, msg):
- dialog = CrumbsMessageDialog(self, glib.markup_escape_text(msg), gtk.MESSAGE_INFO)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- dialog.run()
- dialog.destroy()
- self.build_failed()
-
- def handler_task_started_cb(self, running_build, message):
- fraction = message["current"] * 1.0/message["total"]
- title = "Build packages"
- if self.current_step == self.FAST_IMAGE_GENERATING:
- if message["eventname"] == "sceneQueueTaskStarted":
- fraction = 0.27 * fraction
- elif message["eventname"] == "runQueueTaskStarted":
- fraction = 0.27 + 0.63 * fraction
- elif self.current_step == self.IMAGE_GENERATING:
- title = "Build image"
- if self.previous_step == self.FAST_IMAGE_GENERATING:
- if message["eventname"] == "sceneQueueTaskStarted":
- fraction = 0.27 + 0.63 + 0.03 * fraction
- elif message["eventname"] == "runQueueTaskStarted":
- fraction = 0.27 + 0.63 + 0.03 + 0.07 * fraction
- else:
- if message["eventname"] == "sceneQueueTaskStarted":
- fraction = 0.2 * fraction
- elif message["eventname"] == "runQueueTaskStarted":
- fraction = 0.2 + 0.8 * fraction
- elif self.current_step == self.PACKAGE_GENERATING:
- if message["eventname"] == "sceneQueueTaskStarted":
- fraction = 0.2 * fraction
- elif message["eventname"] == "runQueueTaskStarted":
- fraction = 0.2 + 0.8 * fraction
- self.build_details_page.update_progress_bar(title + ": ", fraction)
- self.build_details_page.update_build_status(message["current"], message["total"], message["task"])
-
- def handler_disk_full_cb(self, running_build):
- self.disk_full = True
-
- def handler_build_failure_cb(self, running_build):
- self.build_details_page.show_issues()
-
- def handler_build_log_cb(self, running_build, func, obj):
- if hasattr(self.logger, func):
- getattr(self.logger, func)(obj)
-
- def destroy_window_cb(self, widget, event):
- if not self.sensitive:
- return True
- elif self.handler.building:
- self.stop_build()
- return True
- else:
- gtk.main_quit()
-
- def event_handle_SIGINT(self, signal, frame):
- for w in gtk.window_list_toplevels():
- if w.get_modal():
- w.response(gtk.RESPONSE_DELETE_EVENT)
- sys.exit(0)
-
- def build_packages(self):
- _, all_recipes = self.recipe_model.get_selected_recipes()
- if not all_recipes:
- lbl = "<b>No selections made</b>"
- msg = "You have not made any selections"
- msg = msg + " so there isn't anything to bake at this time."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_INFO, msg)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- dialog.run()
- dialog.destroy()
- return
- self.generate_packages_async(True)
-
- def build_image(self):
- selected_packages = self.package_model.get_selected_packages()
- if not selected_packages:
- lbl = "<b>No selections made</b>"
- msg = "You have not made any selections"
- msg = msg + " so there isn't anything to bake at this time."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_INFO, msg)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- dialog.run()
- dialog.destroy()
- return
- self.generate_image_async(True)
-
- def just_bake(self):
- selected_image = self.recipe_model.get_selected_image()
- selected_packages = self.package_model.get_selected_packages() or []
-
- # If no base image and no selected packages don't build anything
- if not (selected_packages or selected_image != self.recipe_model.__custom_image__):
- lbl = "<b>No selections made</b>"
- msg = "You have not made any selections"
- msg = msg + " so there isn't anything to bake at this time."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_INFO, msg)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- dialog.run()
- dialog.destroy()
- return
-
- self.fast_generate_image_async(True)
-
- def show_recipe_property_dialog(self, properties):
- information = {}
- dialog = PropertyDialog(title = properties["name"] +' '+ "properties",
- parent = self,
- information = properties,
- flags = gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR)
-
- dialog.set_modal(False)
-
- button = dialog.add_button("Close", gtk.RESPONSE_NO)
- HobAltButton.style_button(button)
- button.connect("clicked", lambda w: dialog.destroy())
-
- dialog.run()
-
- def show_packages_property_dialog(self, properties):
- information = {}
- dialog = PropertyDialog(title = properties["name"] +' '+ "properties",
- parent = self,
- information = properties,
- flags = gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR)
-
- dialog.set_modal(False)
-
- button = dialog.add_button("Close", gtk.RESPONSE_NO)
- HobAltButton.style_button(button)
- button.connect("clicked", lambda w: dialog.destroy())
-
- dialog.run()
-
- def show_layer_selection_dialog(self):
- dialog = LayerSelectionDialog(title = "Layers",
- layers = copy.deepcopy(self.configuration.layers),
- layers_non_removable = copy.deepcopy(self.configuration.layers_non_removable),
- all_layers = self.parameters.all_layers,
- parent = self,
- flags = gtk.DIALOG_MODAL
- | gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR)
- button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
- HobAltButton.style_button(button)
- button = dialog.add_button("OK", gtk.RESPONSE_YES)
- HobButton.style_button(button)
- response = dialog.run()
- if response == gtk.RESPONSE_YES:
- self.configuration.layers = dialog.layers
- # DO refresh layers
- if dialog.layers_changed:
- self.update_config_async()
- dialog.destroy()
-
- def get_image_extension(self):
- image_extension = {}
- for type in self.parameters.image_types:
- ext = self.handler.runCommand(["getVariable", "IMAGE_EXTENSION_%s" % type])
- if ext:
- image_extension[type] = ext.split(' ')
-
- return image_extension
-
- def show_load_my_images_dialog(self):
- image_extension = self.get_image_extension()
- dialog = ImageSelectionDialog(self.parameters.image_addr, self.parameters.image_types,
- "Open My Images", self,
- gtk.FILE_CHOOSER_ACTION_SAVE, None,
- image_extension)
- button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
- HobAltButton.style_button(button)
- button = dialog.add_button("Open", gtk.RESPONSE_YES)
- HobButton.style_button(button)
- response = dialog.run()
- if response == gtk.RESPONSE_YES:
- if not dialog.image_names:
- lbl = "<b>No selections made</b>"
- msg = "You have not made any selections"
- crumbs_dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_INFO, msg)
- button = crumbs_dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- crumbs_dialog.run()
- crumbs_dialog.destroy()
- dialog.destroy()
- return
-
- self.parameters.image_addr = dialog.image_folder
- self.parameters.image_names = dialog.image_names[:]
- self.switch_page(self.MY_IMAGE_OPENED)
-
- dialog.destroy()
-
- def show_adv_settings_dialog(self, tab=None):
- dialog = AdvancedSettingsDialog(title = "Advanced configuration",
- configuration = copy.deepcopy(self.configuration),
- all_image_types = self.parameters.image_types,
- all_package_formats = self.parameters.all_package_formats,
- all_distros = self.parameters.all_distros,
- all_sdk_machines = self.parameters.all_sdk_machines,
- max_threads = self.parameters.max_threads,
- parent = self,
- flags = gtk.DIALOG_MODAL
- | gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR)
- button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
- HobAltButton.style_button(button)
- button = dialog.add_button("Save", gtk.RESPONSE_YES)
- HobButton.style_button(button)
- dialog.set_save_button(button)
- response = dialog.run()
- settings_changed = False
- if response == gtk.RESPONSE_YES:
- self.configuration = dialog.configuration
- self.configuration.save(self.handler, True) # remember settings
- settings_changed = dialog.settings_changed
- dialog.destroy()
- return response == gtk.RESPONSE_YES, settings_changed
-
- def show_simple_settings_dialog(self, tab=None):
- dialog = SimpleSettingsDialog(title = "Settings",
- configuration = copy.deepcopy(self.configuration),
- all_image_types = self.parameters.image_types,
- all_package_formats = self.parameters.all_package_formats,
- all_distros = self.parameters.all_distros,
- all_sdk_machines = self.parameters.all_sdk_machines,
- max_threads = self.parameters.max_threads,
- parent = self,
- flags = gtk.DIALOG_MODAL
- | gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR,
- handler = self.handler)
- button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
- HobAltButton.style_button(button)
- button = dialog.add_button("Save", gtk.RESPONSE_YES)
- HobButton.style_button(button)
- if tab:
- dialog.switch_to_page(tab)
- response = dialog.run()
- settings_changed = False
- if response == gtk.RESPONSE_YES:
- self.configuration = dialog.configuration
- self.configuration.save(self.handler, True) # remember settings
- settings_changed = dialog.settings_changed
- if dialog.proxy_settings_changed:
- self.set_user_config_proxies()
- elif dialog.proxy_test_ran:
- # The user might have modified the proxies in the "Proxy"
- # tab, which in turn made the proxy settings modify in bb.
- # If "Cancel" was pressed, restore the previous proxy
- # settings inside bb.
- self.set_user_config_proxies()
- dialog.destroy()
- return response == gtk.RESPONSE_YES, settings_changed
-
- def reparse_post_adv_settings(self):
- if not self.configuration.curr_mach:
- self.update_config_async()
- else:
- self.configuration.clear_selection()
- # DO reparse recipes
- self.populate_recipe_package_info_async()
-
- def deploy_image(self, image_name):
- if not image_name:
- lbl = "<b>Please select an image to deploy.</b>"
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_INFO)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- dialog.run()
- dialog.destroy()
- return
-
- image_path = os.path.join(self.parameters.image_addr, image_name)
- dialog = DeployImageDialog(title = "Usb Image Maker",
- image_path = image_path,
- parent = self,
- flags = gtk.DIALOG_MODAL
- | gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR)
- button = dialog.add_button("Close", gtk.RESPONSE_NO)
- HobAltButton.style_button(button)
- button = dialog.add_button("Make usb image", gtk.RESPONSE_YES)
- HobButton.style_button(button)
- response = dialog.run()
- dialog.destroy()
-
- def show_load_kernel_dialog(self):
- dialog = gtk.FileChooserDialog("Load Kernel Files", self,
- gtk.FILE_CHOOSER_ACTION_SAVE)
- button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
- HobAltButton.style_button(button)
- button = dialog.add_button("Open", gtk.RESPONSE_YES)
- HobButton.style_button(button)
- filter = gtk.FileFilter()
- filter.set_name("Kernel Files")
- filter.add_pattern("*.bin")
- dialog.add_filter(filter)
-
- dialog.set_current_folder(self.parameters.image_addr)
-
- response = dialog.run()
- kernel_path = ""
- if response == gtk.RESPONSE_YES:
- kernel_path = dialog.get_filename()
-
- dialog.destroy()
-
- return kernel_path
-
- def runqemu_image(self, image_name, kernel_name):
- if not image_name or not kernel_name:
- lbl = "<b>Please select %s to launch in QEMU.</b>" % ("a kernel" if image_name else "an image")
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_INFO)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- dialog.run()
- dialog.destroy()
- return
-
- kernel_path = os.path.join(self.parameters.image_addr, kernel_name)
- image_path = os.path.join(self.parameters.image_addr, image_name)
-
- source_env_path = os.path.join(self.parameters.core_base, "oe-init-build-env")
- tmp_path = self.parameters.tmpdir
- cmdline = bb.ui.crumbs.utils.which_terminal()
- if os.path.exists(image_path) and os.path.exists(kernel_path) \
- and os.path.exists(source_env_path) and os.path.exists(tmp_path) \
- and cmdline:
- cmdline += "\' bash -c \"export OE_TMPDIR=" + tmp_path + "; "
- cmdline += "source " + source_env_path + " " + os.getcwd() + "; "
- cmdline += "runqemu " + kernel_path + " " + image_path + "\"\'"
- subprocess.Popen(shlex.split(cmdline))
- else:
- lbl = "<b>Path error</b>"
- msg = "One of your paths is wrong,"
- msg = msg + " please make sure the following paths exist:\n"
- msg = msg + "image path:" + image_path + "\n"
- msg = msg + "kernel path:" + kernel_path + "\n"
- msg = msg + "source environment path:" + source_env_path + "\n"
- msg = msg + "tmp path: " + tmp_path + "."
- msg = msg + "You may be missing either xterm or vte for terminal services."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_ERROR, msg)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- dialog.run()
- dialog.destroy()
-
- def show_packages(self):
- self.package_details_page.refresh_tables()
- self.switch_page(self.PACKAGE_SELECTION)
-
- def show_recipes(self):
- self.switch_page(self.RECIPE_SELECTION)
-
- def show_image_details(self):
- self.switch_page(self.IMAGE_GENERATED)
-
- def show_configuration(self):
- self.switch_page(self.BASEIMG_SELECTED)
-
- def stop_build(self):
- if self.stopping:
- lbl = "<b>Force Stop build?</b>"
- msg = "You've already selected Stop once,"
- msg = msg + " would you like to 'Force Stop' the build?\n\n"
- msg = msg + "This will stop the build as quickly as possible but may"
- msg = msg + " well leave your build directory in an unusable state"
- msg = msg + " that requires manual steps to fix."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_WARNING, msg)
- button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL)
- HobAltButton.style_button(button)
- button = dialog.add_button("Force Stop", gtk.RESPONSE_YES)
- HobButton.style_button(button)
- else:
- lbl = "<b>Stop build?</b>"
- msg = "Are you sure you want to stop this"
- msg = msg + " build?\n\n'Stop' will stop the build as soon as all in"
- msg = msg + " progress build tasks are finished. However if a"
- msg = msg + " lengthy compilation phase is in progress this may take"
- msg = msg + " some time.\n\n"
- msg = msg + "'Force Stop' will stop the build as quickly as"
- msg = msg + " possible but may well leave your build directory in an"
- msg = msg + " unusable state that requires manual steps to fix."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_WARNING, msg)
- button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL)
- HobAltButton.style_button(button)
- button = dialog.add_button("Force stop", gtk.RESPONSE_YES)
- HobAltButton.style_button(button)
- button = dialog.add_button("Stop", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- response = dialog.run()
- dialog.destroy()
- if response != gtk.RESPONSE_CANCEL:
- self.stopping = True
- if response == gtk.RESPONSE_OK:
- self.build_details_page.progress_bar.set_stop_title("Stopping the build....")
- self.build_details_page.progress_bar.set_rcstyle("stop")
- self.cancel_build_sync()
- elif response == gtk.RESPONSE_YES:
- self.cancel_build_sync(True)
-
- def do_log(self, consolelogfile = None):
- if consolelogfile:
- bb.utils.mkdirhier(os.path.dirname(consolelogfile))
- if self.consolelog:
- self.logger.removeHandler(self.consolelog)
- self.consolelog = None
- self.consolelog = logging.FileHandler(consolelogfile)
- bb.msg.addDefaultlogFilter(self.consolelog)
- format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
- self.consolelog.setFormatter(format)
-
- self.logger.addHandler(self.consolelog)
-
- def get_topdir(self):
- return self.handler.get_topdir()
-
- def wait(self, delay):
- time_start = time.time()
- time_end = time_start + delay
- while time_end > time.time():
- while gtk.events_pending():
- gtk.main_iteration()
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/buildmanager.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/buildmanager.py
deleted file mode 100644
index e858d75e4..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/buildmanager.py
+++ /dev/null
@@ -1,455 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2008 Intel Corporation
-#
-# Authored by Rob Bradford <rob@linux.intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import gtk
-import gobject
-import threading
-import os
-import datetime
-import time
-
-class BuildConfiguration:
- """ Represents a potential *or* historic *or* concrete build. It
- encompasses all the things that we need to tell bitbake to do to make it
- build what we want it to build.
-
- It also stored the metadata URL and the set of possible machines (and the
- distros / images / uris for these. Apart from the metdata URL these are
- not serialised to file (since they may be transient). In some ways this
- functionality might be shifted to the loader class."""
-
- def __init__ (self):
- self.metadata_url = None
-
- # Tuple of (distros, image, urls)
- self.machine_options = {}
-
- self.machine = None
- self.distro = None
- self.image = None
- self.urls = []
- self.extra_urls = []
- self.extra_pkgs = []
-
- def get_machines_model (self):
- model = gtk.ListStore (gobject.TYPE_STRING)
- for machine in self.machine_options.keys():
- model.append ([machine])
-
- return model
-
- def get_distro_and_images_models (self, machine):
- distro_model = gtk.ListStore (gobject.TYPE_STRING)
-
- for distro in self.machine_options[machine][0]:
- distro_model.append ([distro])
-
- image_model = gtk.ListStore (gobject.TYPE_STRING)
-
- for image in self.machine_options[machine][1]:
- image_model.append ([image])
-
- return (distro_model, image_model)
-
- def get_repos (self):
- self.urls = self.machine_options[self.machine][2]
- return self.urls
-
- # It might be a lot lot better if we stored these in like, bitbake conf
- # file format.
- @staticmethod
- def load_from_file (filename):
-
- conf = BuildConfiguration()
- with open(filename, "r") as f:
- for line in f:
- data = line.split (";")[1]
- if (line.startswith ("metadata-url;")):
- conf.metadata_url = data.strip()
- continue
- if (line.startswith ("url;")):
- conf.urls += [data.strip()]
- continue
- if (line.startswith ("extra-url;")):
- conf.extra_urls += [data.strip()]
- continue
- if (line.startswith ("machine;")):
- conf.machine = data.strip()
- continue
- if (line.startswith ("distribution;")):
- conf.distro = data.strip()
- continue
- if (line.startswith ("image;")):
- conf.image = data.strip()
- continue
-
- return conf
-
- # Serialise to a file. This is part of the build process and we use this
- # to be able to repeat a given build (using the same set of parameters)
- # but also so that we can include the details of the image / machine /
- # distro in the build manager tree view.
- def write_to_file (self, filename):
- f = open (filename, "w")
-
- lines = []
-
- if (self.metadata_url):
- lines += ["metadata-url;%s\n" % (self.metadata_url)]
-
- for url in self.urls:
- lines += ["url;%s\n" % (url)]
-
- for url in self.extra_urls:
- lines += ["extra-url;%s\n" % (url)]
-
- if (self.machine):
- lines += ["machine;%s\n" % (self.machine)]
-
- if (self.distro):
- lines += ["distribution;%s\n" % (self.distro)]
-
- if (self.image):
- lines += ["image;%s\n" % (self.image)]
-
- f.writelines (lines)
- f.close ()
-
-class BuildResult(gobject.GObject):
- """ Represents an historic build. Perhaps not successful. But it includes
- things such as the files that are in the directory (the output from the
- build) as well as a deserialised BuildConfiguration file that is stored in
- ".conf" in the directory for the build.
-
- This is GObject so that it can be included in the TreeStore."""
-
- (STATE_COMPLETE, STATE_FAILED, STATE_ONGOING) = \
- (0, 1, 2)
-
- def __init__ (self, parent, identifier):
- gobject.GObject.__init__ (self)
- self.date = None
-
- self.files = []
- self.status = None
- self.identifier = identifier
- self.path = os.path.join (parent, identifier)
-
- # Extract the date, since the directory name is of the
- # format build-<year><month><day>-<ordinal> we can easily
- # pull it out.
- # TODO: Better to stat a file?
- (_, date, revision) = identifier.split ("-")
- print(date)
-
- year = int (date[0:4])
- month = int (date[4:6])
- day = int (date[6:8])
-
- self.date = datetime.date (year, month, day)
-
- self.conf = None
-
- # By default builds are STATE_FAILED unless we find a "complete" file
- # in which case they are STATE_COMPLETE
- self.state = BuildResult.STATE_FAILED
- for file in os.listdir (self.path):
- if (file.startswith (".conf")):
- conffile = os.path.join (self.path, file)
- self.conf = BuildConfiguration.load_from_file (conffile)
- elif (file.startswith ("complete")):
- self.state = BuildResult.STATE_COMPLETE
- else:
- self.add_file (file)
-
- def add_file (self, file):
- # Just add the file for now. Don't care about the type.
- self.files += [(file, None)]
-
-class BuildManagerModel (gtk.TreeStore):
- """ Model for the BuildManagerTreeView. This derives from gtk.TreeStore
- but it abstracts nicely what the columns mean and the setup of the columns
- in the model. """
-
- (COL_IDENT, COL_DESC, COL_MACHINE, COL_DISTRO, COL_BUILD_RESULT, COL_DATE, COL_STATE) = \
- (0, 1, 2, 3, 4, 5, 6)
-
- def __init__ (self):
- gtk.TreeStore.__init__ (self,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_OBJECT,
- gobject.TYPE_INT64,
- gobject.TYPE_INT)
-
-class BuildManager (gobject.GObject):
- """ This class manages the historic builds that have been found in the
- "results" directory but is also used for starting a new build."""
-
- __gsignals__ = {
- 'population-finished' : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- 'populate-error' : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ())
- }
-
- def update_build_result (self, result, iter):
- # Convert the date into something we can sort by.
- date = long (time.mktime (result.date.timetuple()))
-
- # Add a top level entry for the build
-
- self.model.set (iter,
- BuildManagerModel.COL_IDENT, result.identifier,
- BuildManagerModel.COL_DESC, result.conf.image,
- BuildManagerModel.COL_MACHINE, result.conf.machine,
- BuildManagerModel.COL_DISTRO, result.conf.distro,
- BuildManagerModel.COL_BUILD_RESULT, result,
- BuildManagerModel.COL_DATE, date,
- BuildManagerModel.COL_STATE, result.state)
-
- # And then we use the files in the directory as the children for the
- # top level iter.
- for file in result.files:
- self.model.append (iter, (None, file[0], None, None, None, date, -1))
-
- # This function is called as an idle by the BuildManagerPopulaterThread
- def add_build_result (self, result):
- gtk.gdk.threads_enter()
- self.known_builds += [result]
-
- self.update_build_result (result, self.model.append (None))
-
- gtk.gdk.threads_leave()
-
- def notify_build_finished (self):
- # This is a bit of a hack. If we have a running build running then we
- # will have a row in the model in STATE_ONGOING. Find it and make it
- # as if it was a proper historic build (well, it is completed now....)
-
- # We need to use the iters here rather than the Python iterator
- # interface to the model since we need to pass it into
- # update_build_result
-
- iter = self.model.get_iter_first()
-
- while (iter):
- (ident, state) = self.model.get(iter,
- BuildManagerModel.COL_IDENT,
- BuildManagerModel.COL_STATE)
-
- if state == BuildResult.STATE_ONGOING:
- result = BuildResult (self.results_directory, ident)
- self.update_build_result (result, iter)
- iter = self.model.iter_next(iter)
-
- def notify_build_succeeded (self):
- # Write the "complete" file so that when we create the BuildResult
- # object we put into the model
-
- complete_file_path = os.path.join (self.cur_build_directory, "complete")
- f = file (complete_file_path, "w")
- f.close()
- self.notify_build_finished()
-
- def notify_build_failed (self):
- # Without a "complete" file then this will mark the build as failed:
- self.notify_build_finished()
-
- # This function is called as an idle
- def emit_population_finished_signal (self):
- gtk.gdk.threads_enter()
- self.emit ("population-finished")
- gtk.gdk.threads_leave()
-
- class BuildManagerPopulaterThread (threading.Thread):
- def __init__ (self, manager, directory):
- threading.Thread.__init__ (self)
- self.manager = manager
- self.directory = directory
-
- def run (self):
- # For each of the "build-<...>" directories ..
-
- if os.path.exists (self.directory):
- for directory in os.listdir (self.directory):
-
- if not directory.startswith ("build-"):
- continue
-
- build_result = BuildResult (self.directory, directory)
- self.manager.add_build_result (build_result)
-
- gobject.idle_add (BuildManager.emit_population_finished_signal,
- self.manager)
-
- def __init__ (self, server, results_directory):
- gobject.GObject.__init__ (self)
-
- # The builds that we've found from walking the result directory
- self.known_builds = []
-
- # Save out the bitbake server, we need this for issuing commands to
- # the cooker:
- self.server = server
-
- # The TreeStore that we use
- self.model = BuildManagerModel ()
-
- # The results directory is where we create (and look for) the
- # build-<xyz>-<n> directories. We need to populate ourselves from
- # directory
- self.results_directory = results_directory
- self.populate_from_directory (self.results_directory)
-
- def populate_from_directory (self, directory):
- thread = BuildManager.BuildManagerPopulaterThread (self, directory)
- thread.start()
-
- # Come up with the name for the next build ident by combining "build-"
- # with the date formatted as yyyymmdd and then an ordinal. We do this by
- # an optimistic algorithm incrementing the ordinal if we find that it
- # already exists.
- def get_next_build_ident (self):
- today = datetime.date.today ()
- datestr = str (today.year) + str (today.month) + str (today.day)
-
- revision = 0
- test_name = "build-%s-%d" % (datestr, revision)
- test_path = os.path.join (self.results_directory, test_name)
-
- while (os.path.exists (test_path)):
- revision += 1
- test_name = "build-%s-%d" % (datestr, revision)
- test_path = os.path.join (self.results_directory, test_name)
-
- return test_name
-
- # Take a BuildConfiguration and then try and build it based on the
- # parameters of that configuration. S
- def do_build (self, conf):
- server = self.server
-
- # Work out the build directory. Note we actually create the
- # directories here since we need to write the ".conf" file. Otherwise
- # we could have relied on bitbake's builder thread to actually make
- # the directories as it proceeds with the build.
- ident = self.get_next_build_ident ()
- build_directory = os.path.join (self.results_directory,
- ident)
- self.cur_build_directory = build_directory
- os.makedirs (build_directory)
-
- conffile = os.path.join (build_directory, ".conf")
- conf.write_to_file (conffile)
-
- # Add a row to the model representing this ongoing build. It's kinda a
- # fake entry. If this build completes or fails then this gets updated
- # with the real stuff like the historic builds
- date = long (time.time())
- self.model.append (None, (ident, conf.image, conf.machine, conf.distro,
- None, date, BuildResult.STATE_ONGOING))
- try:
- server.runCommand(["setVariable", "BUILD_IMAGES_FROM_FEEDS", 1])
- server.runCommand(["setVariable", "MACHINE", conf.machine])
- server.runCommand(["setVariable", "DISTRO", conf.distro])
- server.runCommand(["setVariable", "PACKAGE_CLASSES", "package_ipk"])
- server.runCommand(["setVariable", "BBFILES", \
- """${OEROOT}/meta/packages/*/*.bb ${OEROOT}/meta-moblin/packages/*/*.bb"""])
- server.runCommand(["setVariable", "TMPDIR", "${OEROOT}/build/tmp"])
- server.runCommand(["setVariable", "IPK_FEED_URIS", \
- " ".join(conf.get_repos())])
- server.runCommand(["setVariable", "DEPLOY_DIR_IMAGE",
- build_directory])
- server.runCommand(["buildTargets", [conf.image], "rootfs"])
-
- except Exception as e:
- print(e)
-
-class BuildManagerTreeView (gtk.TreeView):
- """ The tree view for the build manager. This shows the historic builds
- and so forth. """
-
- # We use this function to control what goes in the cell since we store
- # the date in the model as seconds since the epoch (for sorting) and so we
- # need to make it human readable.
- def date_format_custom_cell_data_func (self, col, cell, model, iter):
- date = model.get (iter, BuildManagerModel.COL_DATE)[0]
- datestr = time.strftime("%A %d %B %Y", time.localtime(date))
- cell.set_property ("text", datestr)
-
- # This format function controls what goes in the cell. We use this to map
- # the integer state to a string and also to colourise the text
- def state_format_custom_cell_data_fun (self, col, cell, model, iter):
- state = model.get (iter, BuildManagerModel.COL_STATE)[0]
-
- if (state == BuildResult.STATE_ONGOING):
- cell.set_property ("text", "Active")
- cell.set_property ("foreground", "#000000")
- elif (state == BuildResult.STATE_FAILED):
- cell.set_property ("text", "Failed")
- cell.set_property ("foreground", "#ff0000")
- elif (state == BuildResult.STATE_COMPLETE):
- cell.set_property ("text", "Complete")
- cell.set_property ("foreground", "#00ff00")
- else:
- cell.set_property ("text", "")
-
- def __init__ (self):
- gtk.TreeView.__init__(self)
-
- # Misc descriptiony thing
- renderer = gtk.CellRendererText ()
- col = gtk.TreeViewColumn (None, renderer,
- text=BuildManagerModel.COL_DESC)
- self.append_column (col)
-
- # Machine
- renderer = gtk.CellRendererText ()
- col = gtk.TreeViewColumn ("Machine", renderer,
- text=BuildManagerModel.COL_MACHINE)
- self.append_column (col)
-
- # distro
- renderer = gtk.CellRendererText ()
- col = gtk.TreeViewColumn ("Distribution", renderer,
- text=BuildManagerModel.COL_DISTRO)
- self.append_column (col)
-
- # date (using a custom function for formatting the cell contents it
- # takes epoch -> human readable string)
- renderer = gtk.CellRendererText ()
- col = gtk.TreeViewColumn ("Date", renderer,
- text=BuildManagerModel.COL_DATE)
- self.append_column (col)
- col.set_cell_data_func (renderer,
- self.date_format_custom_cell_data_func)
-
- # For status.
- renderer = gtk.CellRendererText ()
- col = gtk.TreeViewColumn ("Status", renderer,
- text = BuildManagerModel.COL_STATE)
- self.append_column (col)
- col.set_cell_data_func (renderer,
- self.state_format_custom_cell_data_fun)
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/advancedsettingsdialog.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/advancedsettingsdialog.py
deleted file mode 100644
index e0b3553c2..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/advancedsettingsdialog.py
+++ /dev/null
@@ -1,341 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2011-2012 Intel Corporation
-#
-# Authored by Joshua Lock <josh@linux.intel.com>
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import gtk
-import hashlib
-from bb.ui.crumbs.hobwidget import HobInfoButton, HobButton
-from bb.ui.crumbs.progressbar import HobProgressBar
-from bb.ui.crumbs.hig.settingsuihelper import SettingsUIHelper
-from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
-from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog
-from bb.ui.crumbs.hig.proxydetailsdialog import ProxyDetailsDialog
-
-"""
-The following are convenience classes for implementing GNOME HIG compliant
-BitBake GUI's
-In summary: spacing = 12px, border-width = 6px
-"""
-
-class AdvancedSettingsDialog (CrumbsDialog, SettingsUIHelper):
-
- def details_cb(self, button, parent, protocol):
- dialog = ProxyDetailsDialog(title = protocol.upper() + " Proxy Details",
- user = self.configuration.proxies[protocol][1],
- passwd = self.configuration.proxies[protocol][2],
- parent = parent,
- flags = gtk.DIALOG_MODAL
- | gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR)
- dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_OK)
- response = dialog.run()
- if response == gtk.RESPONSE_OK:
- self.configuration.proxies[protocol][1] = dialog.user
- self.configuration.proxies[protocol][2] = dialog.passwd
- self.refresh_proxy_components()
- dialog.destroy()
-
- def set_save_button(self, button):
- self.save_button = button
-
- def rootfs_combo_changed_cb(self, rootfs_combo, all_package_format, check_hbox):
- combo_item = self.rootfs_combo.get_active_text()
- modified = False
- for child in check_hbox.get_children():
- if isinstance(child, gtk.CheckButton):
- check_hbox.remove(child)
- modified = True
- for format in all_package_format:
- if format != combo_item:
- check_button = gtk.CheckButton(format)
- check_hbox.pack_start(check_button, expand=False, fill=False)
- modified = True
- if modified:
- check_hbox.remove(self.pkgfmt_info)
- check_hbox.pack_start(self.pkgfmt_info, expand=False, fill=False)
- check_hbox.show_all()
-
- def gen_pkgfmt_widget(self, curr_package_format, all_package_format, tooltip_combo="", tooltip_extra=""):
- pkgfmt_vbox = gtk.VBox(False, 6)
-
- label = self.gen_label_widget("Root file system package format")
- pkgfmt_vbox.pack_start(label, expand=False, fill=False)
-
- rootfs_format = ""
- if curr_package_format:
- rootfs_format = curr_package_format.split()[0]
-
- rootfs_format_widget, rootfs_combo = self.gen_combo_widget(rootfs_format, all_package_format, tooltip_combo)
- pkgfmt_vbox.pack_start(rootfs_format_widget, expand=False, fill=False)
-
- label = self.gen_label_widget("Additional package formats")
- pkgfmt_vbox.pack_start(label, expand=False, fill=False)
-
- check_hbox = gtk.HBox(False, 12)
- pkgfmt_vbox.pack_start(check_hbox, expand=False, fill=False)
- for format in all_package_format:
- if format != rootfs_format:
- check_button = gtk.CheckButton(format)
- is_active = (format in curr_package_format.split())
- check_button.set_active(is_active)
- check_hbox.pack_start(check_button, expand=False, fill=False)
-
- self.pkgfmt_info = HobInfoButton(tooltip_extra, self)
- check_hbox.pack_start(self.pkgfmt_info, expand=False, fill=False)
-
- rootfs_combo.connect("changed", self.rootfs_combo_changed_cb, all_package_format, check_hbox)
-
- pkgfmt_vbox.show_all()
-
- return pkgfmt_vbox, rootfs_combo, check_hbox
-
- def __init__(self, title, configuration, all_image_types,
- all_package_formats, all_distros, all_sdk_machines,
- max_threads, parent, flags, buttons=None):
- super(AdvancedSettingsDialog, self).__init__(title, parent, flags, buttons)
-
- # class members from other objects
- # bitbake settings from Builder.Configuration
- self.configuration = configuration
- self.image_types = all_image_types
- self.all_package_formats = all_package_formats
- self.all_distros = all_distros[:]
- self.all_sdk_machines = all_sdk_machines
- self.max_threads = max_threads
-
- # class members for internal use
- self.distro_combo = None
- self.dldir_text = None
- self.sstatedir_text = None
- self.sstatemirror_text = None
- self.bb_spinner = None
- self.pmake_spinner = None
- self.rootfs_size_spinner = None
- self.extra_size_spinner = None
- self.gplv3_checkbox = None
- self.sdk_checkbox = None
- self.image_types_checkbuttons = {}
-
- self.md5 = self.config_md5()
- self.settings_changed = False
-
- # create visual elements on the dialog
- self.save_button = None
- self.create_visual_elements()
- self.connect("response", self.response_cb)
-
- def _get_sorted_value(self, var):
- return " ".join(sorted(str(var).split())) + "\n"
-
- def config_md5(self):
- data = ""
- data += ("PACKAGE_CLASSES: " + self.configuration.curr_package_format + '\n')
- data += ("DISTRO: " + self._get_sorted_value(self.configuration.curr_distro))
- data += ("IMAGE_ROOTFS_SIZE: " + self._get_sorted_value(self.configuration.image_rootfs_size))
- data += ("IMAGE_EXTRA_SIZE: " + self._get_sorted_value(self.configuration.image_extra_size))
- data += ("INCOMPATIBLE_LICENSE: " + self._get_sorted_value(self.configuration.incompat_license))
- data += ("SDK_MACHINE: " + self._get_sorted_value(self.configuration.curr_sdk_machine))
- data += ("TOOLCHAIN_BUILD: " + self._get_sorted_value(self.configuration.toolchain_build))
- data += ("IMAGE_FSTYPES: " + self._get_sorted_value(self.configuration.image_fstypes))
- return hashlib.md5(data).hexdigest()
-
- def create_visual_elements(self):
- self.nb = gtk.Notebook()
- self.nb.set_show_tabs(True)
- self.nb.append_page(self.create_image_types_page(), gtk.Label("Image types"))
- self.nb.append_page(self.create_output_page(), gtk.Label("Output"))
- self.nb.set_current_page(0)
- self.vbox.pack_start(self.nb, expand=True, fill=True)
- self.vbox.pack_end(gtk.HSeparator(), expand=True, fill=True)
-
- self.show_all()
-
- def get_num_checked_image_types(self):
- total = 0
- for b in self.image_types_checkbuttons.values():
- if b.get_active():
- total = total + 1
- return total
-
- def set_save_button_state(self):
- if self.save_button:
- self.save_button.set_sensitive(self.get_num_checked_image_types() > 0)
-
- def image_type_checkbutton_clicked_cb(self, button):
- self.set_save_button_state()
- if self.get_num_checked_image_types() == 0:
- # Show an error dialog
- lbl = "<b>Select an image type</b>"
- msg = "You need to select at least one image type."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_WARNING, msg)
- button = dialog.add_button("OK", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- response = dialog.run()
- dialog.destroy()
-
- def create_image_types_page(self):
- main_vbox = gtk.VBox(False, 16)
- main_vbox.set_border_width(6)
-
- advanced_vbox = gtk.VBox(False, 6)
- advanced_vbox.set_border_width(6)
-
- distro_vbox = gtk.VBox(False, 6)
- label = self.gen_label_widget("Distro:")
- tooltip = "Selects the Yocto Project distribution you want"
- try:
- i = self.all_distros.index( "defaultsetup" )
- except ValueError:
- i = -1
- if i != -1:
- self.all_distros[ i ] = "Default"
- if self.configuration.curr_distro == "defaultsetup":
- self.configuration.curr_distro = "Default"
- distro_widget, self.distro_combo = self.gen_combo_widget(self.configuration.curr_distro, self.all_distros,"<b>Distro</b>" + "*" + tooltip)
- distro_vbox.pack_start(label, expand=False, fill=False)
- distro_vbox.pack_start(distro_widget, expand=False, fill=False)
- main_vbox.pack_start(distro_vbox, expand=False, fill=False)
-
-
- rows = (len(self.image_types)+1)/3
- table = gtk.Table(rows + 1, 10, True)
- advanced_vbox.pack_start(table, expand=False, fill=False)
-
- tooltip = "Image file system types you want."
- info = HobInfoButton("<b>Image types</b>" + "*" + tooltip, self)
- label = self.gen_label_widget("Image types:")
- align = gtk.Alignment(0, 0.5, 0, 0)
- table.attach(align, 0, 4, 0, 1)
- align.add(label)
- table.attach(info, 4, 5, 0, 1)
-
- i = 1
- j = 1
- for image_type in sorted(self.image_types):
- self.image_types_checkbuttons[image_type] = gtk.CheckButton(image_type)
- self.image_types_checkbuttons[image_type].connect("toggled", self.image_type_checkbutton_clicked_cb)
- article = ""
- if image_type.startswith(("a", "e", "i", "o", "u")):
- article = "n"
- if image_type == "live":
- self.image_types_checkbuttons[image_type].set_tooltip_text("Build iso and hddimg images")
- else:
- self.image_types_checkbuttons[image_type].set_tooltip_text("Build a%s %s image" % (article, image_type))
- table.attach(self.image_types_checkbuttons[image_type], j - 1, j + 3, i, i + 1)
- if image_type in self.configuration.image_fstypes.split():
- self.image_types_checkbuttons[image_type].set_active(True)
- i += 1
- if i > rows:
- i = 1
- j = j + 4
-
- main_vbox.pack_start(advanced_vbox, expand=False, fill=False)
- self.set_save_button_state()
-
- return main_vbox
-
- def create_output_page(self):
- advanced_vbox = gtk.VBox(False, 6)
- advanced_vbox.set_border_width(6)
-
- advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Package format</span>'), expand=False, fill=False)
- sub_vbox = gtk.VBox(False, 6)
- advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
- tooltip_combo = "Selects the package format used to generate rootfs."
- tooltip_extra = "Selects extra package formats to build"
- pkgfmt_widget, self.rootfs_combo, self.check_hbox = self.gen_pkgfmt_widget(self.configuration.curr_package_format, self.all_package_formats,"<b>Root file system package format</b>" + "*" + tooltip_combo,"<b>Additional package formats</b>" + "*" + tooltip_extra)
- sub_vbox.pack_start(pkgfmt_widget, expand=False, fill=False)
-
- advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Image size</span>'), expand=False, fill=False)
- sub_vbox = gtk.VBox(False, 6)
- advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
- label = self.gen_label_widget("Image basic size (in MB)")
- tooltip = "Defines the size for the generated image. The OpenEmbedded build system determines the final size for the generated image using an algorithm that takes into account the initial disk space used for the generated image, the Image basic size value, and the Additional free space value.\n\nFor more information, check the <a href=\"http://www.yoctoproject.org/docs/current/poky-ref-manual/poky-ref-manual.html#var-IMAGE_ROOTFS_SIZE\">Yocto Project Reference Manual</a>."
- rootfs_size_widget, self.rootfs_size_spinner = self.gen_spinner_widget(int(self.configuration.image_rootfs_size*1.0/1024), 0, 65536,"<b>Image basic size</b>" + "*" + tooltip)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(rootfs_size_widget, expand=False, fill=False)
-
- sub_vbox = gtk.VBox(False, 6)
- advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
- label = self.gen_label_widget("Additional free space (in MB)")
- tooltip = "Sets extra free disk space to be added to the generated image. Use this variable when you want to ensure that a specific amount of free disk space is available on a device after an image is installed and running."
- extra_size_widget, self.extra_size_spinner = self.gen_spinner_widget(int(self.configuration.image_extra_size*1.0/1024), 0, 65536,"<b>Additional free space</b>" + "*" + tooltip)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(extra_size_widget, expand=False, fill=False)
-
- advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Licensing</span>'), expand=False, fill=False)
- self.gplv3_checkbox = gtk.CheckButton("Exclude GPLv3 packages")
- self.gplv3_checkbox.set_tooltip_text("Check this box to prevent GPLv3 packages from being included in your image")
- if "GPLv3" in self.configuration.incompat_license.split():
- self.gplv3_checkbox.set_active(True)
- else:
- self.gplv3_checkbox.set_active(False)
- advanced_vbox.pack_start(self.gplv3_checkbox, expand=False, fill=False)
-
- advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">SDK</span>'), expand=False, fill=False)
- sub_hbox = gtk.HBox(False, 6)
- advanced_vbox.pack_start(sub_hbox, expand=False, fill=False)
- self.sdk_checkbox = gtk.CheckButton("Populate SDK")
- tooltip = "Check this box to generate an SDK tarball that consists of the cross-toolchain and a sysroot that contains development packages for your image."
- self.sdk_checkbox.set_tooltip_text(tooltip)
- self.sdk_checkbox.set_active(self.configuration.toolchain_build)
- sub_hbox.pack_start(self.sdk_checkbox, expand=False, fill=False)
-
- tooltip = "Select the host platform for which you want to run the toolchain contained in the SDK tarball."
- sdk_machine_widget, self.sdk_machine_combo = self.gen_combo_widget(self.configuration.curr_sdk_machine, self.all_sdk_machines,"<b>Populate SDK</b>" + "*" + tooltip)
- sub_hbox.pack_start(sdk_machine_widget, expand=False, fill=False)
-
- return advanced_vbox
-
- def response_cb(self, dialog, response_id):
- package_format = []
- package_format.append(self.rootfs_combo.get_active_text())
- for child in self.check_hbox:
- if isinstance(child, gtk.CheckButton) and child.get_active():
- package_format.append(child.get_label())
- self.configuration.curr_package_format = " ".join(package_format)
-
- distro = self.distro_combo.get_active_text()
- if distro == "Default":
- distro = "defaultsetup"
- self.configuration.curr_distro = distro
- self.configuration.image_rootfs_size = self.rootfs_size_spinner.get_value_as_int() * 1024
- self.configuration.image_extra_size = self.extra_size_spinner.get_value_as_int() * 1024
-
- self.configuration.image_fstypes = ""
- for image_type in self.image_types:
- if self.image_types_checkbuttons[image_type].get_active():
- self.configuration.image_fstypes += (" " + image_type)
- self.configuration.image_fstypes.strip()
-
- if self.gplv3_checkbox.get_active():
- if "GPLv3" not in self.configuration.incompat_license.split():
- self.configuration.incompat_license += " GPLv3"
- else:
- if "GPLv3" in self.configuration.incompat_license.split():
- self.configuration.incompat_license = self.configuration.incompat_license.split().remove("GPLv3")
- self.configuration.incompat_license = " ".join(self.configuration.incompat_license or [])
- self.configuration.incompat_license = self.configuration.incompat_license.strip()
-
- self.configuration.toolchain_build = self.sdk_checkbox.get_active()
- self.configuration.curr_sdk_machine = self.sdk_machine_combo.get_active_text()
- md5 = self.config_md5()
- self.settings_changed = (self.md5 != md5)
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/parsingwarningsdialog.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/parsingwarningsdialog.py
deleted file mode 100644
index 33bac39db..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/parsingwarningsdialog.py
+++ /dev/null
@@ -1,163 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2011-2012 Intel Corporation
-#
-# Authored by Cristiana Voicu <cristiana.voicu@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import gtk
-import gobject
-from bb.ui.crumbs.hobwidget import HobAltButton
-from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
-
-"""
-The following are convenience classes for implementing GNOME HIG compliant
-BitBake GUI's
-In summary: spacing = 12px, border-width = 6px
-"""
-
-#
-# ParsingWarningsDialog
-#
-class ParsingWarningsDialog (CrumbsDialog):
-
- def __init__(self, title, warnings, parent, flags, buttons=None):
- super(ParsingWarningsDialog, self).__init__(title, parent, flags, buttons)
-
- self.warnings = warnings
- self.warning_on = 0
- self.warn_nb = len(warnings)
-
- # create visual elements on the dialog
- self.create_visual_elements()
-
- def cancel_button_cb(self, button):
- self.destroy()
-
- def previous_button_cb(self, button):
- self.warning_on = self.warning_on - 1
- self.refresh_components()
-
- def next_button_cb(self, button):
- self.warning_on = self.warning_on + 1
- self.refresh_components()
-
- def refresh_components(self):
- lbl = self.warnings[self.warning_on]
- #when the warning text has more than 400 chars, it uses a scroll bar
- if 0<= len(lbl) < 400:
- self.warning_label.set_size_request(320, 230)
- self.warning_label.set_use_markup(True)
- self.warning_label.set_line_wrap(True)
- self.warning_label.set_markup(lbl)
- self.warning_label.set_property("yalign", 0.00)
- else:
- self.textWindow.set_shadow_type(gtk.SHADOW_IN)
- self.textWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
- self.msgView = gtk.TextView()
- self.msgView.set_editable(False)
- self.msgView.set_wrap_mode(gtk.WRAP_WORD)
- self.msgView.set_cursor_visible(False)
- self.msgView.set_size_request(320, 230)
- self.buf = gtk.TextBuffer()
- self.buf.set_text(lbl)
- self.msgView.set_buffer(self.buf)
- self.textWindow.add(self.msgView)
- self.msgView.show()
-
- if self.warning_on==0:
- self.previous_button.set_sensitive(False)
- else:
- self.previous_button.set_sensitive(True)
-
- if self.warning_on==self.warn_nb-1:
- self.next_button.set_sensitive(False)
- else:
- self.next_button.set_sensitive(True)
-
- if self.warn_nb>1:
- self.heading = "Warning " + str(self.warning_on + 1) + " of " + str(self.warn_nb)
- self.heading_label.set_markup('<span weight="bold">%s</span>' % self.heading)
- else:
- self.heading = "Warning"
- self.heading_label.set_markup('<span weight="bold">%s</span>' % self.heading)
-
- self.show_all()
-
- if 0<= len(lbl) < 400:
- self.textWindow.hide()
- else:
- self.warning_label.hide()
-
- def create_visual_elements(self):
- self.set_size_request(350, 350)
- self.heading_label = gtk.Label()
- self.heading_label.set_alignment(0, 0)
- self.warning_label = gtk.Label()
- self.warning_label.set_selectable(True)
- self.warning_label.set_alignment(0, 0)
- self.textWindow = gtk.ScrolledWindow()
-
- table = gtk.Table(1, 10, False)
-
- cancel_button = gtk.Button()
- cancel_button.set_label("Close")
- cancel_button.connect("clicked", self.cancel_button_cb)
- cancel_button.set_size_request(110, 30)
-
- self.previous_button = gtk.Button()
- image1 = gtk.image_new_from_stock(gtk.STOCK_GO_BACK, gtk.ICON_SIZE_BUTTON)
- image1.show()
- box = gtk.HBox(False, 6)
- box.show()
- self.previous_button.add(box)
- lbl = gtk.Label("Previous")
- lbl.show()
- box.pack_start(image1, expand=False, fill=False, padding=3)
- box.pack_start(lbl, expand=True, fill=True, padding=3)
- self.previous_button.connect("clicked", self.previous_button_cb)
- self.previous_button.set_size_request(110, 30)
-
- self.next_button = gtk.Button()
- image2 = gtk.image_new_from_stock(gtk.STOCK_GO_FORWARD, gtk.ICON_SIZE_BUTTON)
- image2.show()
- box = gtk.HBox(False, 6)
- box.show()
- self.next_button.add(box)
- lbl = gtk.Label("Next")
- lbl.show()
- box.pack_start(lbl, expand=True, fill=True, padding=3)
- box.pack_start(image2, expand=False, fill=False, padding=3)
- self.next_button.connect("clicked", self.next_button_cb)
- self.next_button.set_size_request(110, 30)
-
- #when there more than one warning, we need "previous" and "next" button
- if self.warn_nb>1:
- self.vbox.pack_start(self.heading_label, expand=False, fill=False)
- self.vbox.pack_start(self.warning_label, expand=False, fill=False)
- self.vbox.pack_start(self.textWindow, expand=False, fill=False)
- table.attach(cancel_button, 6, 7, 0, 1, xoptions=gtk.SHRINK)
- table.attach(self.previous_button, 7, 8, 0, 1, xoptions=gtk.SHRINK)
- table.attach(self.next_button, 8, 9, 0, 1, xoptions=gtk.SHRINK)
- self.vbox.pack_end(table, expand=False, fill=False)
- else:
- self.vbox.pack_start(self.heading_label, expand=False, fill=False)
- self.vbox.pack_start(self.warning_label, expand=False, fill=False)
- self.vbox.pack_start(self.textWindow, expand=False, fill=False)
- cancel_button = self.add_button("Close", gtk.RESPONSE_CANCEL)
- HobAltButton.style_button(cancel_button)
-
- self.refresh_components()
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/proxydetailsdialog.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/proxydetailsdialog.py
deleted file mode 100644
index 69e7dffb6..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/proxydetailsdialog.py
+++ /dev/null
@@ -1,90 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2011-2012 Intel Corporation
-#
-# Authored by Joshua Lock <josh@linux.intel.com>
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import gtk
-from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
-
-"""
-The following are convenience classes for implementing GNOME HIG compliant
-BitBake GUI's
-In summary: spacing = 12px, border-width = 6px
-"""
-
-class ProxyDetailsDialog (CrumbsDialog):
-
- def __init__(self, title, user, passwd, parent, flags, buttons=None):
- super(ProxyDetailsDialog, self).__init__(title, parent, flags, buttons)
- self.connect("response", self.response_cb)
-
- self.auth = not (user == None or passwd == None or user == "")
- self.user = user or ""
- self.passwd = passwd or ""
-
- # create visual elements on the dialog
- self.create_visual_elements()
-
- def create_visual_elements(self):
- self.auth_checkbox = gtk.CheckButton("Use authentication")
- self.auth_checkbox.set_tooltip_text("Check this box to set the username and the password")
- self.auth_checkbox.set_active(self.auth)
- self.auth_checkbox.connect("toggled", self.auth_checkbox_toggled_cb)
- self.vbox.pack_start(self.auth_checkbox, expand=False, fill=False)
-
- hbox = gtk.HBox(False, 6)
- self.user_label = gtk.Label("Username:")
- self.user_text = gtk.Entry()
- self.user_text.set_text(self.user)
- hbox.pack_start(self.user_label, expand=False, fill=False)
- hbox.pack_end(self.user_text, expand=False, fill=False)
- self.vbox.pack_start(hbox, expand=False, fill=False)
-
- hbox = gtk.HBox(False, 6)
- self.passwd_label = gtk.Label("Password:")
- self.passwd_text = gtk.Entry()
- self.passwd_text.set_text(self.passwd)
- hbox.pack_start(self.passwd_label, expand=False, fill=False)
- hbox.pack_end(self.passwd_text, expand=False, fill=False)
- self.vbox.pack_start(hbox, expand=False, fill=False)
-
- self.refresh_auth_components()
- self.show_all()
-
- def refresh_auth_components(self):
- self.user_label.set_sensitive(self.auth)
- self.user_text.set_editable(self.auth)
- self.user_text.set_sensitive(self.auth)
- self.passwd_label.set_sensitive(self.auth)
- self.passwd_text.set_editable(self.auth)
- self.passwd_text.set_sensitive(self.auth)
-
- def auth_checkbox_toggled_cb(self, button):
- self.auth = self.auth_checkbox.get_active()
- self.refresh_auth_components()
-
- def response_cb(self, dialog, response_id):
- if response_id == gtk.RESPONSE_OK:
- if self.auth:
- self.user = self.user_text.get_text()
- self.passwd = self.passwd_text.get_text()
- else:
- self.user = None
- self.passwd = None
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/retrieveimagedialog.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/retrieveimagedialog.py
deleted file mode 100644
index 901713985..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/retrieveimagedialog.py
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2013 Intel Corporation
-#
-# Authored by Cristiana Voicu <cristiana.voicu@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import gtk
-
-class RetrieveImageDialog (gtk.FileChooserDialog):
- """
- This class is used to create a dialog that permits to retrieve
- a custom image saved previously from Hob.
- """
- def __init__(self, directory,title, parent, flags, buttons=None):
- super(RetrieveImageDialog, self).__init__(title, None, gtk.FILE_CHOOSER_ACTION_OPEN,
- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN, gtk.RESPONSE_OK))
- self.directory = directory
-
- # create visual elements on the dialog
- self.create_visual_elements()
-
- def create_visual_elements(self):
- self.set_show_hidden(True)
- self.set_default_response(gtk.RESPONSE_OK)
- self.set_current_folder(self.directory)
-
- vbox = self.get_children()[0].get_children()[0].get_children()[0]
- for child in vbox.get_children()[0].get_children()[0].get_children()[0].get_children():
- vbox.get_children()[0].get_children()[0].get_children()[0].remove(child)
-
- label1 = gtk.Label()
- label1.set_text("File system" + self.directory)
- label1.show()
- vbox.get_children()[0].get_children()[0].get_children()[0].pack_start(label1, expand=False, fill=False, padding=0)
- vbox.get_children()[0].get_children()[1].get_children()[0].hide()
-
- self.get_children()[0].get_children()[1].get_children()[0].set_label("Select")
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/saveimagedialog.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/saveimagedialog.py
deleted file mode 100644
index 4195f70e1..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/saveimagedialog.py
+++ /dev/null
@@ -1,159 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2013 Intel Corporation
-#
-# Authored by Cristiana Voicu <cristiana.voicu@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import gtk
-import glib
-from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
-from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog
-from bb.ui.crumbs.hobwidget import HobButton
-
-class SaveImageDialog (CrumbsDialog):
- """
- This class is used to create a dialog that permits to save
- a custom image in a predefined directory.
- """
- def __init__(self, directory, name, description, title, parent, flags, buttons=None):
- super(SaveImageDialog, self).__init__(title, parent, flags, buttons)
- self.directory = directory
- self.builder = parent
- self.name_field = name
- self.description_field = description
-
- # create visual elements on the dialog
- self.create_visual_elements()
-
- def create_visual_elements(self):
- self.set_default_response(gtk.RESPONSE_OK)
- self.vbox.set_border_width(6)
-
- sub_vbox = gtk.VBox(False, 12)
- self.vbox.pack_start(sub_vbox, expand=False, fill=False)
- label = gtk.Label()
- label.set_alignment(0, 0)
- label.set_markup("<b>Name</b>")
- sub_label = gtk.Label()
- sub_label.set_alignment(0, 0)
- content = "Image recipe names should be all lowercase and include only alphanumeric\n"
- content += "characters. The only special character you can use is the ASCII hyphen (-)."
- sub_label.set_markup(content)
- self.name_entry = gtk.Entry()
- self.name_entry.set_text(self.name_field)
- self.name_entry.set_size_request(350,30)
- self.name_entry.connect("changed", self.name_entry_changed)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(sub_label, expand=False, fill=False)
- sub_vbox.pack_start(self.name_entry, expand=False, fill=False)
-
- sub_vbox = gtk.VBox(False, 12)
- self.vbox.pack_start(sub_vbox, expand=False, fill=False)
- label = gtk.Label()
- label.set_alignment(0, 0)
- label.set_markup("<b>Description</b> (optional)")
- sub_label = gtk.Label()
- sub_label.set_alignment(0, 0)
- sub_label.set_markup("The description should be less than 150 characters long.")
- self.description_entry = gtk.TextView()
- description_buffer = self.description_entry.get_buffer()
- description_buffer.set_text(self.description_field)
- description_buffer.connect("insert-text", self.limit_description_length)
- self.description_entry.set_wrap_mode(gtk.WRAP_WORD)
- self.description_entry.set_size_request(350,50)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(sub_label, expand=False, fill=False)
- sub_vbox.pack_start(self.description_entry, expand=False, fill=False)
-
- sub_vbox = gtk.VBox(False, 12)
- self.vbox.pack_start(sub_vbox, expand=False, fill=False)
- label = gtk.Label()
- label.set_alignment(0, 0)
- label.set_markup("Your image recipe will be saved to:")
- sub_label = gtk.Label()
- sub_label.set_alignment(0, 0)
- sub_label.set_markup(self.directory)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(sub_label, expand=False, fill=False)
-
- table = gtk.Table(1, 4, True)
-
- cancel_button = gtk.Button()
- cancel_button.set_label("Cancel")
- cancel_button.connect("clicked", self.cancel_button_cb)
- cancel_button.set_size_request(110, 30)
-
- self.save_button = gtk.Button()
- self.save_button.set_label("Save")
- self.save_button.connect("clicked", self.save_button_cb)
- self.save_button.set_size_request(110, 30)
- if self.name_entry.get_text() == '':
- self.save_button.set_sensitive(False)
-
- table.attach(cancel_button, 2, 3, 0, 1)
- table.attach(self.save_button, 3, 4, 0, 1)
- self.vbox.pack_end(table, expand=False, fill=False)
-
- self.show_all()
-
- def limit_description_length(self, textbuffer, iter, text, length):
- buffer_bounds = textbuffer.get_bounds()
- entire_text = textbuffer.get_text(*buffer_bounds)
- entire_text += text
- if len(entire_text)>150 or text=="\n":
- textbuffer.emit_stop_by_name("insert-text")
-
- def name_entry_changed(self, entry):
- text = entry.get_text()
- if text == '':
- self.save_button.set_sensitive(False)
- else:
- self.save_button.set_sensitive(True)
-
- def cancel_button_cb(self, button):
- self.destroy()
-
- def save_button_cb(self, button):
- text = self.name_entry.get_text()
- new_text = text.replace("-","")
- description_buffer = self.description_entry.get_buffer()
- description = description_buffer.get_text(description_buffer.get_start_iter(),description_buffer.get_end_iter())
- if new_text.islower() and new_text.isalnum():
- self.builder.image_details_page.image_saved = True
- self.builder.customized = False
- self.builder.generate_new_image(self.directory+text, description)
- self.builder.recipe_model.set_in_list(text, description)
- self.builder.recipe_model.set_selected_image(text)
- self.builder.image_details_page.show_page(self.builder.IMAGE_GENERATED)
- self.builder.image_details_page.name_field_template = text
- self.builder.image_details_page.description_field_template = description
- self.destroy()
- else:
- self.show_invalid_input_error_dialog()
-
- def show_invalid_input_error_dialog(self):
- lbl = "<b>Invalid characters in image recipe name</b>"
- msg = "Image recipe names should be all lowercase and\n"
- msg += "include only alphanumeric characters. The only\n"
- msg += "special character you can use is the ASCII hyphen (-)."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_ERROR, msg)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
-
- res = dialog.run()
- self.name_entry.grab_focus()
- dialog.destroy()
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/simplesettingsdialog.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/simplesettingsdialog.py
deleted file mode 100644
index b5eb3d873..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/simplesettingsdialog.py
+++ /dev/null
@@ -1,891 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2011-2012 Intel Corporation
-#
-# Authored by Joshua Lock <josh@linux.intel.com>
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import gtk
-import gobject
-import hashlib
-from bb.ui.crumbs.hobwidget import hic, HobInfoButton, HobButton, HobAltButton
-from bb.ui.crumbs.progressbar import HobProgressBar
-from bb.ui.crumbs.hig.settingsuihelper import SettingsUIHelper
-from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
-from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog
-from bb.ui.crumbs.hig.proxydetailsdialog import ProxyDetailsDialog
-
-"""
-The following are convenience classes for implementing GNOME HIG compliant
-BitBake GUI's
-In summary: spacing = 12px, border-width = 6px
-"""
-
-class SimpleSettingsDialog (CrumbsDialog, SettingsUIHelper):
-
- (BUILD_ENV_PAGE_ID,
- SHARED_STATE_PAGE_ID,
- PROXIES_PAGE_ID,
- OTHERS_PAGE_ID) = range(4)
-
- (TEST_NETWORK_NONE,
- TEST_NETWORK_INITIAL,
- TEST_NETWORK_RUNNING,
- TEST_NETWORK_PASSED,
- TEST_NETWORK_FAILED,
- TEST_NETWORK_CANCELED) = range(6)
-
- TARGETS = [
- ("MY_TREE_MODEL_ROW", gtk.TARGET_SAME_WIDGET, 0),
- ("text/plain", 0, 1),
- ("TEXT", 0, 2),
- ("STRING", 0, 3),
- ]
-
- def __init__(self, title, configuration, all_image_types,
- all_package_formats, all_distros, all_sdk_machines,
- max_threads, parent, flags, handler, buttons=None):
- super(SimpleSettingsDialog, self).__init__(title, parent, flags, buttons)
-
- # class members from other objects
- # bitbake settings from Builder.Configuration
- self.configuration = configuration
- self.image_types = all_image_types
- self.all_package_formats = all_package_formats
- self.all_distros = all_distros
- self.all_sdk_machines = all_sdk_machines
- self.max_threads = max_threads
-
- # class members for internal use
- self.dldir_text = None
- self.sstatedir_text = None
- self.sstatemirrors_list = []
- self.sstatemirrors_changed = 0
- self.bb_spinner = None
- self.pmake_spinner = None
- self.rootfs_size_spinner = None
- self.extra_size_spinner = None
- self.gplv3_checkbox = None
- self.toolchain_checkbox = None
- self.setting_store = None
- self.image_types_checkbuttons = {}
-
- self.md5 = self.config_md5()
- self.proxy_md5 = self.config_proxy_md5()
- self.settings_changed = False
- self.proxy_settings_changed = False
- self.handler = handler
- self.proxy_test_ran = False
- self.selected_mirror_row = 0
- self.new_mirror = False
-
- # create visual elements on the dialog
- self.create_visual_elements()
- self.connect("response", self.response_cb)
-
- def _get_sorted_value(self, var):
- return " ".join(sorted(str(var).split())) + "\n"
-
- def config_proxy_md5(self):
- data = ("ENABLE_PROXY: " + self._get_sorted_value(self.configuration.enable_proxy))
- if self.configuration.enable_proxy:
- for protocol in self.configuration.proxies.keys():
- data += (protocol + ": " + self._get_sorted_value(self.configuration.combine_proxy(protocol)))
- return hashlib.md5(data).hexdigest()
-
- def config_md5(self):
- data = ""
- for key in self.configuration.extra_setting.keys():
- data += (key + ": " + self._get_sorted_value(self.configuration.extra_setting[key]))
- return hashlib.md5(data).hexdigest()
-
- def gen_proxy_entry_widget(self, protocol, parent, need_button=True, line=0):
- label = gtk.Label(protocol.upper() + " proxy")
- self.proxy_table.attach(label, 0, 1, line, line+1, xpadding=24)
-
- proxy_entry = gtk.Entry()
- proxy_entry.set_size_request(300, -1)
- self.proxy_table.attach(proxy_entry, 1, 2, line, line+1, ypadding=4)
-
- self.proxy_table.attach(gtk.Label(":"), 2, 3, line, line+1, xpadding=12, ypadding=4)
-
- port_entry = gtk.Entry()
- port_entry.set_size_request(60, -1)
- self.proxy_table.attach(port_entry, 3, 4, line, line+1, ypadding=4)
-
- details_button = HobAltButton("Details")
- details_button.connect("clicked", self.details_cb, parent, protocol)
- self.proxy_table.attach(details_button, 4, 5, line, line+1, xpadding=4, yoptions=gtk.EXPAND)
-
- return proxy_entry, port_entry, details_button
-
- def refresh_proxy_components(self):
- self.same_checkbox.set_sensitive(self.configuration.enable_proxy)
-
- self.http_proxy.set_text(self.configuration.combine_host_only("http"))
- self.http_proxy.set_editable(self.configuration.enable_proxy)
- self.http_proxy.set_sensitive(self.configuration.enable_proxy)
- self.http_proxy_port.set_text(self.configuration.combine_port_only("http"))
- self.http_proxy_port.set_editable(self.configuration.enable_proxy)
- self.http_proxy_port.set_sensitive(self.configuration.enable_proxy)
- self.http_proxy_details.set_sensitive(self.configuration.enable_proxy)
-
- self.https_proxy.set_text(self.configuration.combine_host_only("https"))
- self.https_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.https_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.https_proxy_port.set_text(self.configuration.combine_port_only("https"))
- self.https_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.https_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.https_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
-
- self.ftp_proxy.set_text(self.configuration.combine_host_only("ftp"))
- self.ftp_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.ftp_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.ftp_proxy_port.set_text(self.configuration.combine_port_only("ftp"))
- self.ftp_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.ftp_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.ftp_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
-
- self.socks_proxy.set_text(self.configuration.combine_host_only("socks"))
- self.socks_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.socks_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.socks_proxy_port.set_text(self.configuration.combine_port_only("socks"))
- self.socks_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.socks_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.socks_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
-
- self.cvs_proxy.set_text(self.configuration.combine_host_only("cvs"))
- self.cvs_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.cvs_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.cvs_proxy_port.set_text(self.configuration.combine_port_only("cvs"))
- self.cvs_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.cvs_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.cvs_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
-
- if self.configuration.same_proxy:
- if self.http_proxy.get_text():
- [w.set_text(self.http_proxy.get_text()) for w in self.same_proxy_addresses]
- if self.http_proxy_port.get_text():
- [w.set_text(self.http_proxy_port.get_text()) for w in self.same_proxy_ports]
-
- def proxy_checkbox_toggled_cb(self, button):
- self.configuration.enable_proxy = self.proxy_checkbox.get_active()
- if not self.configuration.enable_proxy:
- self.configuration.same_proxy = False
- self.same_checkbox.set_active(self.configuration.same_proxy)
- self.save_proxy_data()
- self.refresh_proxy_components()
-
- def same_checkbox_toggled_cb(self, button):
- self.configuration.same_proxy = self.same_checkbox.get_active()
- self.save_proxy_data()
- self.refresh_proxy_components()
-
- def save_proxy_data(self):
- self.configuration.split_proxy("http", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
- if self.configuration.same_proxy:
- self.configuration.split_proxy("https", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
- self.configuration.split_proxy("ftp", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
- self.configuration.split_proxy("socks", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
- self.configuration.split_proxy("cvs", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
- else:
- self.configuration.split_proxy("https", self.https_proxy.get_text() + ":" + self.https_proxy_port.get_text())
- self.configuration.split_proxy("ftp", self.ftp_proxy.get_text() + ":" + self.ftp_proxy_port.get_text())
- self.configuration.split_proxy("socks", self.socks_proxy.get_text() + ":" + self.socks_proxy_port.get_text())
- self.configuration.split_proxy("cvs", self.cvs_proxy.get_text() + ":" + self.cvs_proxy_port.get_text())
-
- def response_cb(self, dialog, response_id):
- if response_id == gtk.RESPONSE_YES:
- if self.proxy_checkbox.get_active():
- # Check that all proxy entries have a corresponding port
- for proxy, port in zip(self.all_proxy_addresses, self.all_proxy_ports):
- if proxy.get_text() and not port.get_text():
- lbl = "<b>Enter all port numbers</b>"
- msg = "Proxy servers require a port number. Please make sure you have entered a port number for each proxy server."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_WARNING, msg)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- response = dialog.run()
- dialog.destroy()
- self.emit_stop_by_name("response")
- return
-
- self.configuration.dldir = self.dldir_text.get_text()
- self.configuration.sstatedir = self.sstatedir_text.get_text()
- self.configuration.sstatemirror = ""
- for mirror in self.sstatemirrors_list:
- if mirror[1] != "" and mirror[2].startswith("file://"):
- smirror = mirror[2] + " " + mirror[1] + " \\n "
- self.configuration.sstatemirror += smirror
- self.configuration.bbthread = self.bb_spinner.get_value_as_int()
- self.configuration.pmake = self.pmake_spinner.get_value_as_int()
- self.save_proxy_data()
- self.configuration.extra_setting = {}
- it = self.setting_store.get_iter_first()
- while it:
- key = self.setting_store.get_value(it, 0)
- value = self.setting_store.get_value(it, 1)
- self.configuration.extra_setting[key] = value
- it = self.setting_store.iter_next(it)
-
- md5 = self.config_md5()
- self.settings_changed = (self.md5 != md5)
- self.proxy_settings_changed = (self.proxy_md5 != self.config_proxy_md5())
-
- def create_build_environment_page(self):
- advanced_vbox = gtk.VBox(False, 6)
- advanced_vbox.set_border_width(6)
-
- advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Parallel threads</span>'), expand=False, fill=False)
- sub_vbox = gtk.VBox(False, 6)
- advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
- label = self.gen_label_widget("BitBake parallel threads")
- tooltip = "Sets the number of threads that BitBake tasks can simultaneously run. See the <a href=\""
- tooltip += "http://www.yoctoproject.org/docs/current/poky-ref-manual/"
- tooltip += "poky-ref-manual.html#var-BB_NUMBER_THREADS\">Poky reference manual</a> for information"
- bbthread_widget, self.bb_spinner = self.gen_spinner_widget(self.configuration.bbthread, 1, self.max_threads,"<b>BitBake prallalel threads</b>" + "*" + tooltip)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(bbthread_widget, expand=False, fill=False)
-
- sub_vbox = gtk.VBox(False, 6)
- advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
- label = self.gen_label_widget("Make parallel threads")
- tooltip = "Sets the maximum number of threads the host can use during the build. See the <a href=\""
- tooltip += "http://www.yoctoproject.org/docs/current/poky-ref-manual/"
- tooltip += "poky-ref-manual.html#var-PARALLEL_MAKE\">Poky reference manual</a> for information"
- pmake_widget, self.pmake_spinner = self.gen_spinner_widget(self.configuration.pmake, 1, self.max_threads,"<b>Make parallel threads</b>" + "*" + tooltip)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(pmake_widget, expand=False, fill=False)
-
- advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Downloaded source code</span>'), expand=False, fill=False)
- sub_vbox = gtk.VBox(False, 6)
- advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
- label = self.gen_label_widget("Downloads directory")
- tooltip = "Select a folder that caches the upstream project source code"
- dldir_widget, self.dldir_text = self.gen_entry_widget(self.configuration.dldir, self,"<b>Downloaded source code</b>" + "*" + tooltip)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(dldir_widget, expand=False, fill=False)
-
- return advanced_vbox
-
- def create_shared_state_page(self):
- advanced_vbox = gtk.VBox(False)
- advanced_vbox.set_border_width(12)
-
- sub_vbox = gtk.VBox(False)
- advanced_vbox.pack_start(sub_vbox, expand=False, fill=False, padding=24)
- content = "<span>Shared state directory</span>"
- tooltip = "Select a folder that caches your prebuilt results"
- label = self.gen_label_info_widget(content,"<b>Shared state directory</b>" + "*" + tooltip)
- sstatedir_widget, self.sstatedir_text = self.gen_entry_widget(self.configuration.sstatedir, self)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(sstatedir_widget, expand=False, fill=False, padding=6)
-
- content = "<span weight=\"bold\">Shared state mirrors</span>"
- tooltip = "URLs pointing to pre-built mirrors that will speed your build. "
- tooltip += "Select the \'Standard\' configuration if the structure of your "
- tooltip += "mirror replicates the structure of your local shared state directory. "
- tooltip += "For more information on shared state mirrors, check the <a href=\""
- tooltip += "http://www.yoctoproject.org/docs/current/poky-ref-manual/"
- tooltip += "poky-ref-manual.html#shared-state\">Yocto Project Reference Manual</a>."
- table = self.gen_label_info_widget(content,"<b>Shared state mirrors</b>" + "*" + tooltip)
- advanced_vbox.pack_start(table, expand=False, fill=False, padding=6)
-
- sub_vbox = gtk.VBox(False)
- advanced_vbox.pack_start(sub_vbox, gtk.TRUE, gtk.TRUE, 0)
-
- if self.sstatemirrors_changed == 0:
- self.sstatemirrors_changed = 1
- sstatemirrors = self.configuration.sstatemirror
- if sstatemirrors == "":
- sm_list = ["Standard", "", "file://(.*)"]
- self.sstatemirrors_list.append(sm_list)
- else:
- sstatemirrors = [x for x in sstatemirrors.split('\\n')]
- for sstatemirror in sstatemirrors:
- sstatemirror_fields = [x for x in sstatemirror.split(' ') if x.strip()]
- if len(sstatemirror_fields) == 2:
- if sstatemirror_fields[0] == "file://(.*)" or sstatemirror_fields[0] == "file://.*":
- sm_list = ["Standard", sstatemirror_fields[1], sstatemirror_fields[0]]
- else:
- sm_list = ["Custom", sstatemirror_fields[1], sstatemirror_fields[0]]
- self.sstatemirrors_list.append(sm_list)
-
- sstatemirrors_widget, sstatemirrors_store = self.gen_shared_sstate_widget(self.sstatemirrors_list, self)
- sub_vbox.pack_start(sstatemirrors_widget, expand=True, fill=True)
-
- table = gtk.Table(1, 10, False)
- table.set_col_spacings(6)
- add_mirror_button = HobAltButton("Add mirror")
- add_mirror_button.connect("clicked", self.add_mirror)
- add_mirror_button.set_size_request(120,30)
- table.attach(add_mirror_button, 1, 2, 0, 1, xoptions=gtk.SHRINK)
-
- self.delete_button = HobAltButton("Delete mirror")
- self.delete_button.connect("clicked", self.delete_cb)
- self.delete_button.set_size_request(120, 30)
- table.attach(self.delete_button, 3, 4, 0, 1, xoptions=gtk.SHRINK)
-
- advanced_vbox.pack_start(table, expand=False, fill=False, padding=6)
-
- return advanced_vbox
-
- def gen_shared_sstate_widget(self, sstatemirrors_list, window):
- hbox = gtk.HBox(False)
-
- sstatemirrors_store = gtk.ListStore(str, str, str)
- for sstatemirror in sstatemirrors_list:
- sstatemirrors_store.append(sstatemirror)
-
- self.sstatemirrors_tv = gtk.TreeView()
- self.sstatemirrors_tv.set_rules_hint(True)
- self.sstatemirrors_tv.set_headers_visible(True)
- tree_selection = self.sstatemirrors_tv.get_selection()
- tree_selection.set_mode(gtk.SELECTION_SINGLE)
-
- # Allow enable drag and drop of rows including row move
- self.sstatemirrors_tv.enable_model_drag_source( gtk.gdk.BUTTON1_MASK,
- self.TARGETS,
- gtk.gdk.ACTION_DEFAULT|
- gtk.gdk.ACTION_MOVE)
- self.sstatemirrors_tv.enable_model_drag_dest(self.TARGETS,
- gtk.gdk.ACTION_DEFAULT)
- self.sstatemirrors_tv.connect("drag_data_get", self.drag_data_get_cb)
- self.sstatemirrors_tv.connect("drag_data_received", self.drag_data_received_cb)
-
-
- self.scroll = gtk.ScrolledWindow()
- self.scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
- self.scroll.set_shadow_type(gtk.SHADOW_IN)
- self.scroll.connect('size-allocate', self.scroll_changed)
- self.scroll.add(self.sstatemirrors_tv)
-
- #list store for cell renderer
- m = gtk.ListStore(gobject.TYPE_STRING)
- m.append(["Standard"])
- m.append(["Custom"])
-
- cell0 = gtk.CellRendererCombo()
- cell0.set_property("model",m)
- cell0.set_property("text-column", 0)
- cell0.set_property("editable", True)
- cell0.set_property("has-entry", False)
- col0 = gtk.TreeViewColumn("Configuration")
- col0.pack_start(cell0, False)
- col0.add_attribute(cell0, "text", 0)
- col0.set_cell_data_func(cell0, self.configuration_field)
- self.sstatemirrors_tv.append_column(col0)
-
- cell0.connect("edited", self.combo_changed, sstatemirrors_store)
-
- self.cell1 = gtk.CellRendererText()
- self.cell1.set_padding(5,2)
- col1 = gtk.TreeViewColumn('Regex', self.cell1)
- col1.set_cell_data_func(self.cell1, self.regex_field)
- self.sstatemirrors_tv.append_column(col1)
-
- self.cell1.connect("edited", self.regex_changed, sstatemirrors_store)
-
- cell2 = gtk.CellRendererText()
- cell2.set_padding(5,2)
- cell2.set_property("editable", True)
- col2 = gtk.TreeViewColumn('URL', cell2)
- col2.set_cell_data_func(cell2, self.url_field)
- self.sstatemirrors_tv.append_column(col2)
-
- cell2.connect("edited", self.url_changed, sstatemirrors_store)
-
- self.sstatemirrors_tv.set_model(sstatemirrors_store)
- self.sstatemirrors_tv.set_cursor(self.selected_mirror_row)
- hbox.pack_start(self.scroll, expand=True, fill=True)
- hbox.show_all()
-
- return hbox, sstatemirrors_store
-
- def drag_data_get_cb(self, treeview, context, selection, target_id, etime):
- treeselection = treeview.get_selection()
- model, iter = treeselection.get_selected()
- data = model.get_string_from_iter(iter)
- selection.set(selection.target, 8, data)
-
- def drag_data_received_cb(self, treeview, context, x, y, selection, info, etime):
- model = treeview.get_model()
- data = []
- tree_iter = model.get_iter_from_string(selection.data)
- data.append(model.get_value(tree_iter, 0))
- data.append(model.get_value(tree_iter, 1))
- data.append(model.get_value(tree_iter, 2))
-
- drop_info = treeview.get_dest_row_at_pos(x, y)
- if drop_info:
- path, position = drop_info
- iter = model.get_iter(path)
- if (position == gtk.TREE_VIEW_DROP_BEFORE or position == gtk.TREE_VIEW_DROP_INTO_OR_BEFORE):
- model.insert_before(iter, data)
- else:
- model.insert_after(iter, data)
- else:
- model.append(data)
- if context.action == gtk.gdk.ACTION_MOVE:
- context.finish(True, True, etime)
- return
-
- def delete_cb(self, button):
- selection = self.sstatemirrors_tv.get_selection()
- tree_model, tree_iter = selection.get_selected()
- index = int(tree_model.get_string_from_iter(tree_iter))
- if index == 0:
- self.selected_mirror_row = index
- else:
- self.selected_mirror_row = index - 1
- self.sstatemirrors_list.pop(index)
- self.refresh_shared_state_page()
- if not self.sstatemirrors_list:
- self.delete_button.set_sensitive(False)
-
- def add_mirror(self, button):
- self.new_mirror = True
- tooltip = "Select the pre-built mirror that will speed your build"
- index = len(self.sstatemirrors_list)
- self.selected_mirror_row = index
- sm_list = ["Standard", "", "file://(.*)"]
- self.sstatemirrors_list.append(sm_list)
- self.refresh_shared_state_page()
-
- def scroll_changed(self, widget, event, data=None):
- if self.new_mirror == True:
- adj = widget.get_vadjustment()
- adj.set_value(adj.upper - adj.page_size)
- self.new_mirror = False
-
- def combo_changed(self, widget, path, text, model):
- model[path][0] = text
- selection = self.sstatemirrors_tv.get_selection()
- tree_model, tree_iter = selection.get_selected()
- index = int(tree_model.get_string_from_iter(tree_iter))
- self.sstatemirrors_list[index][0] = text
-
- def regex_changed(self, cell, path, new_text, user_data):
- user_data[path][2] = new_text
- selection = self.sstatemirrors_tv.get_selection()
- tree_model, tree_iter = selection.get_selected()
- index = int(tree_model.get_string_from_iter(tree_iter))
- self.sstatemirrors_list[index][2] = new_text
- return
-
- def url_changed(self, cell, path, new_text, user_data):
- if new_text!="Enter the mirror URL" and new_text!="Match regex and replace it with this URL":
- user_data[path][1] = new_text
- selection = self.sstatemirrors_tv.get_selection()
- tree_model, tree_iter = selection.get_selected()
- index = int(tree_model.get_string_from_iter(tree_iter))
- self.sstatemirrors_list[index][1] = new_text
- return
-
- def configuration_field(self, column, cell, model, iter):
- cell.set_property('text', model.get_value(iter, 0))
- if model.get_value(iter, 0) == "Standard":
- self.cell1.set_property("sensitive", False)
- self.cell1.set_property("editable", False)
- else:
- self.cell1.set_property("sensitive", True)
- self.cell1.set_property("editable", True)
- return
-
- def regex_field(self, column, cell, model, iter):
- cell.set_property('text', model.get_value(iter, 2))
- return
-
- def url_field(self, column, cell, model, iter):
- text = model.get_value(iter, 1)
- if text == "":
- if model.get_value(iter, 0) == "Standard":
- text = "Enter the mirror URL"
- else:
- text = "Match regex and replace it with this URL"
- cell.set_property('text', text)
- return
-
- def refresh_shared_state_page(self):
- page_num = self.nb.get_current_page()
- self.nb.remove_page(page_num);
- self.nb.insert_page(self.create_shared_state_page(), gtk.Label("Shared state"),page_num)
- self.show_all()
- self.nb.set_current_page(page_num)
-
- def test_proxy_ended(self, passed):
- self.proxy_test_running = False
- self.set_test_proxy_state(self.TEST_NETWORK_PASSED if passed else self.TEST_NETWORK_FAILED)
- self.set_sensitive(True)
- self.refresh_proxy_components()
-
- def timer_func(self):
- self.test_proxy_progress.pulse()
- return self.proxy_test_running
-
- def test_network_button_cb(self, b):
- self.set_test_proxy_state(self.TEST_NETWORK_RUNNING)
- self.set_sensitive(False)
- self.save_proxy_data()
- if self.configuration.enable_proxy == True:
- self.handler.set_http_proxy(self.configuration.combine_proxy("http"))
- self.handler.set_https_proxy(self.configuration.combine_proxy("https"))
- self.handler.set_ftp_proxy(self.configuration.combine_proxy("ftp"))
- self.handler.set_socks_proxy(self.configuration.combine_proxy("socks"))
- self.handler.set_cvs_proxy(self.configuration.combine_host_only("cvs"), self.configuration.combine_port_only("cvs"))
- elif self.configuration.enable_proxy == False:
- self.handler.set_http_proxy("")
- self.handler.set_https_proxy("")
- self.handler.set_ftp_proxy("")
- self.handler.set_socks_proxy("")
- self.handler.set_cvs_proxy("", "")
- self.proxy_test_ran = True
- self.proxy_test_running = True
- gobject.timeout_add(100, self.timer_func)
- self.handler.trigger_network_test()
-
- def test_proxy_focus_event(self, w, direction):
- if self.test_proxy_state in [self.TEST_NETWORK_PASSED, self.TEST_NETWORK_FAILED]:
- self.set_test_proxy_state(self.TEST_NETWORK_INITIAL)
- return False
-
- def http_proxy_changed(self, e):
- if not self.configuration.same_proxy:
- return
- if e == self.http_proxy:
- [w.set_text(self.http_proxy.get_text()) for w in self.same_proxy_addresses]
- else:
- [w.set_text(self.http_proxy_port.get_text()) for w in self.same_proxy_ports]
-
- def proxy_address_focus_out_event(self, w, direction):
- text = w.get_text()
- if not text:
- return False
- if text.find("//") == -1:
- w.set_text("http://" + text)
- return False
-
- def set_test_proxy_state(self, state):
- if self.test_proxy_state == state:
- return
- [self.proxy_table.remove(w) for w in self.test_gui_elements]
- if state == self.TEST_NETWORK_INITIAL:
- self.proxy_table.attach(self.test_network_button, 1, 2, 5, 6)
- self.test_network_button.show()
- elif state == self.TEST_NETWORK_RUNNING:
- self.test_proxy_progress.set_rcstyle("running")
- self.test_proxy_progress.set_text("Testing network configuration")
- self.proxy_table.attach(self.test_proxy_progress, 0, 5, 5, 6, xpadding=4)
- self.test_proxy_progress.show()
- else: # passed or failed
- self.dummy_progress.update(1.0)
- if state == self.TEST_NETWORK_PASSED:
- self.dummy_progress.set_text("Your network is properly configured")
- self.dummy_progress.set_rcstyle("running")
- else:
- self.dummy_progress.set_text("Network test failed")
- self.dummy_progress.set_rcstyle("fail")
- self.proxy_table.attach(self.dummy_progress, 0, 4, 5, 6)
- self.proxy_table.attach(self.retest_network_button, 4, 5, 5, 6, xpadding=4)
- self.dummy_progress.show()
- self.retest_network_button.show()
- self.test_proxy_state = state
-
- def create_network_page(self):
- advanced_vbox = gtk.VBox(False, 6)
- advanced_vbox.set_border_width(6)
- self.same_proxy_addresses = []
- self.same_proxy_ports = []
- self.all_proxy_ports = []
- self.all_proxy_addresses = []
-
- sub_vbox = gtk.VBox(False, 6)
- advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
- label = self.gen_label_widget("<span weight=\"bold\">Set the proxies used when fetching source code</span>")
- tooltip = "Set the proxies used when fetching source code. A blank field uses a direct internet connection."
- info = HobInfoButton("<span weight=\"bold\">Set the proxies used when fetching source code</span>" + "*" + tooltip, self)
- hbox = gtk.HBox(False, 12)
- hbox.pack_start(label, expand=True, fill=True)
- hbox.pack_start(info, expand=False, fill=False)
- sub_vbox.pack_start(hbox, expand=False, fill=False)
-
- proxy_test_focus = []
- self.direct_checkbox = gtk.RadioButton(None, "Direct network connection")
- proxy_test_focus.append(self.direct_checkbox)
- self.direct_checkbox.set_tooltip_text("Check this box to use a direct internet connection with no proxy")
- self.direct_checkbox.set_active(not self.configuration.enable_proxy)
- sub_vbox.pack_start(self.direct_checkbox, expand=False, fill=False)
-
- self.proxy_checkbox = gtk.RadioButton(self.direct_checkbox, "Manual proxy configuration")
- proxy_test_focus.append(self.proxy_checkbox)
- self.proxy_checkbox.set_tooltip_text("Check this box to manually set up a specific proxy")
- self.proxy_checkbox.set_active(self.configuration.enable_proxy)
- sub_vbox.pack_start(self.proxy_checkbox, expand=False, fill=False)
-
- self.same_checkbox = gtk.CheckButton("Use the HTTP proxy for all protocols")
- proxy_test_focus.append(self.same_checkbox)
- self.same_checkbox.set_tooltip_text("Check this box to use the HTTP proxy for all five proxies")
- self.same_checkbox.set_active(self.configuration.same_proxy)
- hbox = gtk.HBox(False, 12)
- hbox.pack_start(self.same_checkbox, expand=False, fill=False, padding=24)
- sub_vbox.pack_start(hbox, expand=False, fill=False)
-
- self.proxy_table = gtk.Table(6, 5, False)
- self.http_proxy, self.http_proxy_port, self.http_proxy_details = self.gen_proxy_entry_widget(
- "http", self, True, 0)
- proxy_test_focus +=[self.http_proxy, self.http_proxy_port]
- self.http_proxy.connect("changed", self.http_proxy_changed)
- self.http_proxy_port.connect("changed", self.http_proxy_changed)
-
- self.https_proxy, self.https_proxy_port, self.https_proxy_details = self.gen_proxy_entry_widget(
- "https", self, True, 1)
- proxy_test_focus += [self.https_proxy, self.https_proxy_port]
- self.same_proxy_addresses.append(self.https_proxy)
- self.same_proxy_ports.append(self.https_proxy_port)
-
- self.ftp_proxy, self.ftp_proxy_port, self.ftp_proxy_details = self.gen_proxy_entry_widget(
- "ftp", self, True, 2)
- proxy_test_focus += [self.ftp_proxy, self.ftp_proxy_port]
- self.same_proxy_addresses.append(self.ftp_proxy)
- self.same_proxy_ports.append(self.ftp_proxy_port)
-
- self.socks_proxy, self.socks_proxy_port, self.socks_proxy_details = self.gen_proxy_entry_widget(
- "socks", self, True, 3)
- proxy_test_focus += [self.socks_proxy, self.socks_proxy_port]
- self.same_proxy_addresses.append(self.socks_proxy)
- self.same_proxy_ports.append(self.socks_proxy_port)
-
- self.cvs_proxy, self.cvs_proxy_port, self.cvs_proxy_details = self.gen_proxy_entry_widget(
- "cvs", self, True, 4)
- proxy_test_focus += [self.cvs_proxy, self.cvs_proxy_port]
- self.same_proxy_addresses.append(self.cvs_proxy)
- self.same_proxy_ports.append(self.cvs_proxy_port)
- self.all_proxy_ports = self.same_proxy_ports + [self.http_proxy_port]
- self.all_proxy_addresses = self.same_proxy_addresses + [self.http_proxy]
- sub_vbox.pack_start(self.proxy_table, expand=False, fill=False)
- self.proxy_table.show_all()
-
- # Create the graphical elements for the network test feature, but don't display them yet
- self.test_network_button = HobAltButton("Test network configuration")
- self.test_network_button.connect("clicked", self.test_network_button_cb)
- self.test_proxy_progress = HobProgressBar()
- self.dummy_progress = HobProgressBar()
- self.retest_network_button = HobAltButton("Retest")
- self.retest_network_button.connect("clicked", self.test_network_button_cb)
- self.test_gui_elements = [self.test_network_button, self.test_proxy_progress, self.dummy_progress, self.retest_network_button]
- # Initialize the network tester
- self.test_proxy_state = self.TEST_NETWORK_NONE
- self.set_test_proxy_state(self.TEST_NETWORK_INITIAL)
- self.proxy_test_passed_id = self.handler.connect("network-passed", lambda h:self.test_proxy_ended(True))
- self.proxy_test_failed_id = self.handler.connect("network-failed", lambda h:self.test_proxy_ended(False))
- [w.connect("focus-in-event", self.test_proxy_focus_event) for w in proxy_test_focus]
- [w.connect("focus-out-event", self.proxy_address_focus_out_event) for w in self.all_proxy_addresses]
-
- self.direct_checkbox.connect("toggled", self.proxy_checkbox_toggled_cb)
- self.proxy_checkbox.connect("toggled", self.proxy_checkbox_toggled_cb)
- self.same_checkbox.connect("toggled", self.same_checkbox_toggled_cb)
-
- self.refresh_proxy_components()
- return advanced_vbox
-
- def switch_to_page(self, page_id):
- self.nb.set_current_page(page_id)
-
- def details_cb(self, button, parent, protocol):
- self.save_proxy_data()
- dialog = ProxyDetailsDialog(title = protocol.upper() + " Proxy Details",
- user = self.configuration.proxies[protocol][1],
- passwd = self.configuration.proxies[protocol][2],
- parent = parent,
- flags = gtk.DIALOG_MODAL
- | gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR)
- dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_OK)
- response = dialog.run()
- if response == gtk.RESPONSE_OK:
- self.configuration.proxies[protocol][1] = dialog.user
- self.configuration.proxies[protocol][2] = dialog.passwd
- self.refresh_proxy_components()
- dialog.destroy()
-
- def rootfs_combo_changed_cb(self, rootfs_combo, all_package_format, check_hbox):
- combo_item = self.rootfs_combo.get_active_text()
- for child in check_hbox.get_children():
- if isinstance(child, gtk.CheckButton):
- check_hbox.remove(child)
- for format in all_package_format:
- if format != combo_item:
- check_button = gtk.CheckButton(format)
- check_hbox.pack_start(check_button, expand=False, fill=False)
- check_hbox.show_all()
-
- def gen_pkgfmt_widget(self, curr_package_format, all_package_format, tooltip_combo="", tooltip_extra=""):
- pkgfmt_hbox = gtk.HBox(False, 24)
-
- rootfs_vbox = gtk.VBox(False, 6)
- pkgfmt_hbox.pack_start(rootfs_vbox, expand=False, fill=False)
-
- label = self.gen_label_widget("Root file system package format")
- rootfs_vbox.pack_start(label, expand=False, fill=False)
-
- rootfs_format = ""
- if curr_package_format:
- rootfs_format = curr_package_format.split()[0]
-
- rootfs_format_widget, rootfs_combo = self.gen_combo_widget(rootfs_format, all_package_format, tooltip_combo)
- rootfs_vbox.pack_start(rootfs_format_widget, expand=False, fill=False)
-
- extra_vbox = gtk.VBox(False, 6)
- pkgfmt_hbox.pack_start(extra_vbox, expand=False, fill=False)
-
- label = self.gen_label_widget("Additional package formats")
- extra_vbox.pack_start(label, expand=False, fill=False)
-
- check_hbox = gtk.HBox(False, 12)
- extra_vbox.pack_start(check_hbox, expand=False, fill=False)
- for format in all_package_format:
- if format != rootfs_format:
- check_button = gtk.CheckButton(format)
- is_active = (format in curr_package_format.split())
- check_button.set_active(is_active)
- check_hbox.pack_start(check_button, expand=False, fill=False)
-
- info = HobInfoButton(tooltip_extra, self)
- check_hbox.pack_end(info, expand=False, fill=False)
-
- rootfs_combo.connect("changed", self.rootfs_combo_changed_cb, all_package_format, check_hbox)
-
- pkgfmt_hbox.show_all()
-
- return pkgfmt_hbox, rootfs_combo, check_hbox
-
- def editable_settings_cell_edited(self, cell, path_string, new_text, model):
- it = model.get_iter_from_string(path_string)
- column = cell.get_data("column")
- model.set(it, column, new_text)
-
- def editable_settings_add_item_clicked(self, button, model):
- new_item = ["##KEY##", "##VALUE##"]
-
- iter = model.append()
- model.set (iter,
- 0, new_item[0],
- 1, new_item[1],
- )
-
- def editable_settings_remove_item_clicked(self, button, treeview):
- selection = treeview.get_selection()
- model, iter = selection.get_selected()
-
- if iter:
- path = model.get_path(iter)[0]
- model.remove(iter)
-
- def gen_editable_settings(self, setting, tooltip=""):
- setting_hbox = gtk.HBox(False, 12)
-
- vbox = gtk.VBox(False, 12)
- setting_hbox.pack_start(vbox, expand=True, fill=True)
-
- setting_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
- for key in setting.keys():
- setting_store.set(setting_store.append(), 0, key, 1, setting[key])
-
- setting_tree = gtk.TreeView(setting_store)
- setting_tree.set_headers_visible(True)
- setting_tree.set_size_request(300, 100)
-
- col = gtk.TreeViewColumn('Key')
- col.set_min_width(100)
- col.set_max_width(150)
- col.set_resizable(True)
- col1 = gtk.TreeViewColumn('Value')
- col1.set_min_width(100)
- col1.set_max_width(150)
- col1.set_resizable(True)
- setting_tree.append_column(col)
- setting_tree.append_column(col1)
- cell = gtk.CellRendererText()
- cell.set_property('width-chars', 10)
- cell.set_property('editable', True)
- cell.set_data("column", 0)
- cell.connect("edited", self.editable_settings_cell_edited, setting_store)
- cell1 = gtk.CellRendererText()
- cell1.set_property('width-chars', 10)
- cell1.set_property('editable', True)
- cell1.set_data("column", 1)
- cell1.connect("edited", self.editable_settings_cell_edited, setting_store)
- col.pack_start(cell, True)
- col1.pack_end(cell1, True)
- col.set_attributes(cell, text=0)
- col1.set_attributes(cell1, text=1)
-
- scroll = gtk.ScrolledWindow()
- scroll.set_shadow_type(gtk.SHADOW_IN)
- scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
- scroll.add(setting_tree)
- vbox.pack_start(scroll, expand=True, fill=True)
-
- # some buttons
- hbox = gtk.HBox(True, 6)
- vbox.pack_start(hbox, False, False)
-
- button = gtk.Button(stock=gtk.STOCK_ADD)
- button.connect("clicked", self.editable_settings_add_item_clicked, setting_store)
- hbox.pack_start(button)
-
- button = gtk.Button(stock=gtk.STOCK_REMOVE)
- button.connect("clicked", self.editable_settings_remove_item_clicked, setting_tree)
- hbox.pack_start(button)
-
- info = HobInfoButton(tooltip, self)
- setting_hbox.pack_start(info, expand=False, fill=False)
-
- return setting_hbox, setting_store
-
- def create_others_page(self):
- advanced_vbox = gtk.VBox(False, 6)
- advanced_vbox.set_border_width(6)
-
- sub_vbox = gtk.VBox(False, 6)
- advanced_vbox.pack_start(sub_vbox, expand=True, fill=True)
- label = self.gen_label_widget("<span weight=\"bold\">Add your own variables:</span>")
- tooltip = "These are key/value pairs for your extra settings. Click \'Add\' and then directly edit the key and the value"
- setting_widget, self.setting_store = self.gen_editable_settings(self.configuration.extra_setting,"<b>Add your own variables</b>" + "*" + tooltip)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(setting_widget, expand=True, fill=True)
-
- return advanced_vbox
-
- def create_visual_elements(self):
- self.nb = gtk.Notebook()
- self.nb.set_show_tabs(True)
- self.nb.append_page(self.create_build_environment_page(), gtk.Label("Build environment"))
- self.nb.append_page(self.create_shared_state_page(), gtk.Label("Shared state"))
- self.nb.append_page(self.create_network_page(), gtk.Label("Network"))
- self.nb.append_page(self.create_others_page(), gtk.Label("Others"))
- self.nb.set_current_page(0)
- self.vbox.pack_start(self.nb, expand=True, fill=True)
- self.vbox.pack_end(gtk.HSeparator(), expand=True, fill=True)
-
- self.show_all()
-
- def destroy(self):
- self.handler.disconnect(self.proxy_test_passed_id)
- self.handler.disconnect(self.proxy_test_failed_id)
- super(SimpleSettingsDialog, self).destroy()
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/hobeventhandler.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/hobeventhandler.py
deleted file mode 100644
index b71fb33d3..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/hobeventhandler.py
+++ /dev/null
@@ -1,645 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2011 Intel Corporation
-#
-# Authored by Joshua Lock <josh@linux.intel.com>
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import gobject
-import logging
-import ast
-from bb.ui.crumbs.runningbuild import RunningBuild
-
-class HobHandler(gobject.GObject):
-
- """
- This object does BitBake event handling for the hob gui.
- """
- __gsignals__ = {
- "package-formats-updated" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT,)),
- "config-updated" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_STRING, gobject.TYPE_PYOBJECT,)),
- "command-succeeded" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_INT,)),
- "command-failed" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_STRING,)),
- "parsing-warning" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_STRING,)),
- "sanity-failed" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_STRING, gobject.TYPE_INT)),
- "generating-data" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- "data-generated" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- "parsing-started" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT,)),
- "parsing" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT,)),
- "parsing-completed" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT,)),
- "recipe-populated" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- "package-populated" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- "network-passed" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- "network-failed" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- }
-
- (GENERATE_CONFIGURATION, GENERATE_RECIPES, GENERATE_PACKAGES, GENERATE_IMAGE, POPULATE_PACKAGEINFO, SANITY_CHECK, NETWORK_TEST) = range(7)
- (SUB_PATH_LAYERS, SUB_FILES_DISTRO, SUB_FILES_MACH, SUB_FILES_SDKMACH, SUB_MATCH_CLASS, SUB_PARSE_CONFIG, SUB_SANITY_CHECK,
- SUB_GNERATE_TGTS, SUB_GENERATE_PKGINFO, SUB_BUILD_RECIPES, SUB_BUILD_IMAGE, SUB_NETWORK_TEST) = range(12)
-
- def __init__(self, server, recipe_model, package_model):
- super(HobHandler, self).__init__()
-
- self.build = RunningBuild(sequential=True)
-
- self.recipe_model = recipe_model
- self.package_model = package_model
-
- self.commands_async = []
- self.generating = False
- self.current_phase = None
- self.building = False
- self.recipe_queue = []
- self.package_queue = []
-
- self.server = server
- self.error_msg = ""
- self.initcmd = None
- self.parsing = False
-
- def set_busy(self):
- if not self.generating:
- self.emit("generating-data")
- self.generating = True
-
- def clear_busy(self):
- if self.generating:
- self.emit("data-generated")
- self.generating = False
-
- def runCommand(self, commandline):
- try:
- result, error = self.server.runCommand(commandline)
- if error:
- raise Exception("Error running command '%s': %s" % (commandline, error))
- return result
- except Exception as e:
- self.commands_async = []
- self.clear_busy()
- self.emit("command-failed", "Hob Exception - %s" % (str(e)))
- return None
-
- def run_next_command(self, initcmd=None):
- if initcmd != None:
- self.initcmd = initcmd
-
- if self.commands_async:
- self.set_busy()
- next_command = self.commands_async.pop(0)
- else:
- self.clear_busy()
- if self.initcmd != None:
- self.emit("command-succeeded", self.initcmd)
- return
-
- if next_command == self.SUB_PATH_LAYERS:
- self.runCommand(["findConfigFilePath", "bblayers.conf"])
- elif next_command == self.SUB_FILES_DISTRO:
- self.runCommand(["findConfigFiles", "DISTRO"])
- elif next_command == self.SUB_FILES_MACH:
- self.runCommand(["findConfigFiles", "MACHINE"])
- elif next_command == self.SUB_FILES_SDKMACH:
- self.runCommand(["findConfigFiles", "MACHINE-SDK"])
- elif next_command == self.SUB_MATCH_CLASS:
- self.runCommand(["findFilesMatchingInDir", "rootfs_", "classes"])
- elif next_command == self.SUB_PARSE_CONFIG:
- self.runCommand(["resetCooker"])
- elif next_command == self.SUB_GNERATE_TGTS:
- self.runCommand(["generateTargetsTree", "classes/image.bbclass", []])
- elif next_command == self.SUB_GENERATE_PKGINFO:
- self.runCommand(["triggerEvent", "bb.event.RequestPackageInfo()"])
- elif next_command == self.SUB_SANITY_CHECK:
- self.runCommand(["triggerEvent", "bb.event.SanityCheck()"])
- elif next_command == self.SUB_NETWORK_TEST:
- self.runCommand(["triggerEvent", "bb.event.NetworkTest()"])
- elif next_command == self.SUB_BUILD_RECIPES:
- self.clear_busy()
- self.building = True
- self.runCommand(["buildTargets", self.recipe_queue, self.default_task])
- self.recipe_queue = []
- elif next_command == self.SUB_BUILD_IMAGE:
- self.clear_busy()
- self.building = True
- target = self.image
-
- if self.base_image:
- # Request the build of a custom image
- self.generate_hob_base_image(target)
- self.set_var_in_file("LINGUAS_INSTALL", "", "local.conf")
- hobImage = self.runCommand(["matchFile", target + ".bb"])
- if self.base_image != self.recipe_model.__custom_image__:
- baseImage = self.runCommand(["matchFile", self.base_image + ".bb"])
- version = self.runCommand(["generateNewImage", hobImage, baseImage, self.package_queue, True, ""])
- target += version
- self.recipe_model.set_custom_image_version(version)
-
- targets = [target]
- if self.toolchain_packages:
- self.set_var_in_file("TOOLCHAIN_TARGET_TASK", " ".join(self.toolchain_packages), "local.conf")
- targets.append(target + ":do_populate_sdk")
-
- self.runCommand(["buildTargets", targets, self.default_task])
-
- def display_error(self):
- self.clear_busy()
- self.emit("command-failed", self.error_msg)
- self.error_msg = ""
- if self.building:
- self.building = False
-
- def handle_event(self, event):
- if not event:
- return
- if self.building:
- self.current_phase = "building"
- self.build.handle_event(event)
-
- if isinstance(event, bb.event.PackageInfo):
- self.package_model.populate(event._pkginfolist)
- self.emit("package-populated")
- self.run_next_command()
-
- elif isinstance(event, bb.event.SanityCheckPassed):
- reparse = self.runCommand(["getVariable", "BB_INVALIDCONF"]) or None
- if reparse is True:
- self.set_var_in_file("BB_INVALIDCONF", False, "local.conf")
- self.runCommand(["setPrePostConfFiles", "conf/.hob.conf", ""])
- self.commands_async.prepend(self.SUB_PARSE_CONFIG)
- self.run_next_command()
-
- elif isinstance(event, bb.event.SanityCheckFailed):
- self.emit("sanity-failed", event._msg, event._network_error)
-
- elif isinstance(event, logging.LogRecord):
- if not self.building:
- if event.levelno >= logging.ERROR:
- formatter = bb.msg.BBLogFormatter()
- msg = formatter.format(event)
- self.error_msg += msg + '\n'
- elif event.levelno >= logging.WARNING and self.parsing == True:
- formatter = bb.msg.BBLogFormatter()
- msg = formatter.format(event)
- warn_msg = msg + '\n'
- self.emit("parsing-warning", warn_msg)
-
- elif isinstance(event, bb.event.TargetsTreeGenerated):
- self.current_phase = "data generation"
- if event._model:
- self.recipe_model.populate(event._model)
- self.emit("recipe-populated")
- elif isinstance(event, bb.event.ConfigFilesFound):
- self.current_phase = "configuration lookup"
- var = event._variable
- values = event._values
- values.sort()
- self.emit("config-updated", var, values)
- elif isinstance(event, bb.event.ConfigFilePathFound):
- self.current_phase = "configuration lookup"
- elif isinstance(event, bb.event.FilesMatchingFound):
- self.current_phase = "configuration lookup"
- # FIXME: hard coding, should at least be a variable shared between
- # here and the caller
- if event._pattern == "rootfs_":
- formats = []
- for match in event._matches:
- classname, sep, cls = match.rpartition(".")
- fs, sep, format = classname.rpartition("_")
- formats.append(format)
- formats.sort()
- self.emit("package-formats-updated", formats)
- elif isinstance(event, bb.command.CommandCompleted):
- self.current_phase = None
- self.run_next_command()
- elif isinstance(event, bb.command.CommandFailed):
- if event.error not in ("Forced shutdown", "Stopped build"):
- self.error_msg += event.error
- self.commands_async = []
- self.display_error()
- elif isinstance(event, (bb.event.ParseStarted,
- bb.event.CacheLoadStarted,
- bb.event.TreeDataPreparationStarted,
- )):
- message = {}
- message["eventname"] = bb.event.getName(event)
- message["current"] = 0
- message["total"] = None
- message["title"] = "Parsing recipes"
- self.emit("parsing-started", message)
- if isinstance(event, bb.event.ParseStarted):
- self.parsing = True
- elif isinstance(event, (bb.event.ParseProgress,
- bb.event.CacheLoadProgress,
- bb.event.TreeDataPreparationProgress)):
- message = {}
- message["eventname"] = bb.event.getName(event)
- message["current"] = event.current
- message["total"] = event.total
- message["title"] = "Parsing recipes"
- self.emit("parsing", message)
- elif isinstance(event, (bb.event.ParseCompleted,
- bb.event.CacheLoadCompleted,
- bb.event.TreeDataPreparationCompleted)):
- message = {}
- message["eventname"] = bb.event.getName(event)
- message["current"] = event.total
- message["total"] = event.total
- message["title"] = "Parsing recipes"
- self.emit("parsing-completed", message)
- if isinstance(event, bb.event.ParseCompleted):
- self.parsing = False
- elif isinstance(event, bb.event.NetworkTestFailed):
- self.emit("network-failed")
- self.run_next_command()
- elif isinstance(event, bb.event.NetworkTestPassed):
- self.emit("network-passed")
- self.run_next_command()
-
- if self.error_msg and not self.commands_async:
- self.display_error()
-
- return
-
- def init_cooker(self):
- self.runCommand(["createConfigFile", ".hob.conf"])
-
- def set_extra_inherit(self, bbclass):
- self.append_var_in_file("INHERIT", bbclass, ".hob.conf")
-
- def set_bblayers(self, bblayers):
- self.set_var_in_file("BBLAYERS", " ".join(bblayers), "bblayers.conf")
-
- def set_machine(self, machine):
- if machine:
- self.early_assign_var_in_file("MACHINE", machine, "local.conf")
-
- def set_sdk_machine(self, sdk_machine):
- self.set_var_in_file("SDKMACHINE", sdk_machine, "local.conf")
-
- def set_image_fstypes(self, image_fstypes):
- self.set_var_in_file("IMAGE_FSTYPES", image_fstypes, "local.conf")
-
- def set_distro(self, distro):
- self.set_var_in_file("DISTRO", distro, "local.conf")
-
- def set_package_format(self, format):
- package_classes = ""
- for pkgfmt in format.split():
- package_classes += ("package_%s" % pkgfmt + " ")
- self.set_var_in_file("PACKAGE_CLASSES", package_classes, "local.conf")
-
- def set_bbthreads(self, threads):
- self.set_var_in_file("BB_NUMBER_THREADS", threads, "local.conf")
-
- def set_pmake(self, threads):
- pmake = "-j %s" % threads
- self.set_var_in_file("PARALLEL_MAKE", pmake, "local.conf")
-
- def set_dl_dir(self, directory):
- self.set_var_in_file("DL_DIR", directory, "local.conf")
-
- def set_sstate_dir(self, directory):
- self.set_var_in_file("SSTATE_DIR", directory, "local.conf")
-
- def set_sstate_mirrors(self, url):
- self.set_var_in_file("SSTATE_MIRRORS", url, "local.conf")
-
- def set_extra_size(self, image_extra_size):
- self.set_var_in_file("IMAGE_ROOTFS_EXTRA_SPACE", str(image_extra_size), "local.conf")
-
- def set_rootfs_size(self, image_rootfs_size):
- self.set_var_in_file("IMAGE_ROOTFS_SIZE", str(image_rootfs_size), "local.conf")
-
- def set_incompatible_license(self, incompat_license):
- self.set_var_in_file("INCOMPATIBLE_LICENSE", incompat_license, "local.conf")
-
- def set_extra_setting(self, extra_setting):
- self.set_var_in_file("EXTRA_SETTING", extra_setting, "local.conf")
-
- def set_extra_config(self, extra_setting):
- old_extra_setting = self.runCommand(["getVariable", "EXTRA_SETTING"]) or {}
- old_extra_setting = str(old_extra_setting)
-
- old_extra_setting = ast.literal_eval(old_extra_setting)
- if not type(old_extra_setting) == dict:
- old_extra_setting = {}
-
- # settings not changed
- if old_extra_setting == extra_setting:
- return
-
- # remove the old EXTRA SETTING variable
- self.remove_var_from_file("EXTRA_SETTING")
-
- # remove old settings from conf
- for key in old_extra_setting.keys():
- if key not in extra_setting:
- self.remove_var_from_file(key)
-
- # add new settings
- for key, value in extra_setting.iteritems():
- self.set_var_in_file(key, value, "local.conf")
-
- if extra_setting:
- self.set_var_in_file("EXTRA_SETTING", extra_setting, "local.conf")
-
- def set_http_proxy(self, http_proxy):
- self.set_var_in_file("http_proxy", http_proxy, "local.conf")
-
- def set_https_proxy(self, https_proxy):
- self.set_var_in_file("https_proxy", https_proxy, "local.conf")
-
- def set_ftp_proxy(self, ftp_proxy):
- self.set_var_in_file("ftp_proxy", ftp_proxy, "local.conf")
-
- def set_socks_proxy(self, socks_proxy):
- self.set_var_in_file("all_proxy", socks_proxy, "local.conf")
-
- def set_cvs_proxy(self, host, port):
- self.set_var_in_file("CVS_PROXY_HOST", host, "local.conf")
- self.set_var_in_file("CVS_PROXY_PORT", port, "local.conf")
-
- def request_package_info(self):
- self.commands_async.append(self.SUB_GENERATE_PKGINFO)
- self.run_next_command(self.POPULATE_PACKAGEINFO)
-
- def trigger_sanity_check(self):
- self.commands_async.append(self.SUB_SANITY_CHECK)
- self.run_next_command(self.SANITY_CHECK)
-
- def trigger_network_test(self):
- self.commands_async.append(self.SUB_NETWORK_TEST)
- self.run_next_command(self.NETWORK_TEST)
-
- def generate_configuration(self):
- self.runCommand(["setPrePostConfFiles", "conf/.hob.conf", ""])
- self.commands_async.append(self.SUB_PARSE_CONFIG)
- self.commands_async.append(self.SUB_PATH_LAYERS)
- self.commands_async.append(self.SUB_FILES_DISTRO)
- self.commands_async.append(self.SUB_FILES_MACH)
- self.commands_async.append(self.SUB_FILES_SDKMACH)
- self.commands_async.append(self.SUB_MATCH_CLASS)
- self.run_next_command(self.GENERATE_CONFIGURATION)
-
- def generate_recipes(self):
- self.runCommand(["setPrePostConfFiles", "conf/.hob.conf", ""])
- self.commands_async.append(self.SUB_PARSE_CONFIG)
- self.commands_async.append(self.SUB_GNERATE_TGTS)
- self.run_next_command(self.GENERATE_RECIPES)
-
- def generate_packages(self, tgts, default_task="build"):
- targets = []
- targets.extend(tgts)
- self.recipe_queue = targets
- self.default_task = default_task
- self.runCommand(["setPrePostConfFiles", "conf/.hob.conf", ""])
- self.commands_async.append(self.SUB_PARSE_CONFIG)
- self.commands_async.append(self.SUB_BUILD_RECIPES)
- self.run_next_command(self.GENERATE_PACKAGES)
-
- def generate_image(self, image, base_image, image_packages=None, toolchain_packages=None, default_task="build"):
- self.image = image
- self.base_image = base_image
- if image_packages:
- self.package_queue = image_packages
- else:
- self.package_queue = []
- if toolchain_packages:
- self.toolchain_packages = toolchain_packages
- else:
- self.toolchain_packages = []
- self.default_task = default_task
- self.runCommand(["setPrePostConfFiles", "conf/.hob.conf", ""])
- self.commands_async.append(self.SUB_PARSE_CONFIG)
- self.commands_async.append(self.SUB_BUILD_IMAGE)
- self.run_next_command(self.GENERATE_IMAGE)
-
- def generate_new_image(self, image, base_image, package_queue, description):
- if base_image:
- base_image = self.runCommand(["matchFile", self.base_image + ".bb"])
- self.runCommand(["generateNewImage", image, base_image, package_queue, False, description])
-
- def generate_hob_base_image(self, hob_image):
- image_dir = self.get_topdir() + "/recipes/images/"
- recipe_name = hob_image + ".bb"
- self.ensure_dir(image_dir)
- self.generate_new_image(image_dir + recipe_name, None, [], "")
-
- def ensure_dir(self, directory):
- self.runCommand(["ensureDir", directory])
-
- def build_succeeded_async(self):
- self.building = False
-
- def build_failed_async(self):
- self.initcmd = None
- self.commands_async = []
- self.building = False
-
- def cancel_parse(self):
- self.runCommand(["stateForceShutdown"])
-
- def cancel_build(self, force=False):
- if force:
- # Force the cooker to stop as quickly as possible
- self.runCommand(["stateForceShutdown"])
- else:
- # Wait for tasks to complete before shutting down, this helps
- # leave the workdir in a usable state
- self.runCommand(["stateShutdown"])
-
- def reset_build(self):
- self.build.reset()
-
- def get_logfile(self):
- return self.server.runCommand(["getVariable", "BB_CONSOLELOG"])[0]
-
- def get_topdir(self):
- return self.runCommand(["getVariable", "TOPDIR"]) or ""
-
- def _remove_redundant(self, string):
- ret = []
- for i in string.split():
- if i not in ret:
- ret.append(i)
- return " ".join(ret)
-
- def set_var_in_file(self, var, val, default_file=None):
- self.runCommand(["enableDataTracking"])
- self.server.runCommand(["setVarFile", var, val, default_file, "set"])
- self.runCommand(["disableDataTracking"])
-
- def early_assign_var_in_file(self, var, val, default_file=None):
- self.runCommand(["enableDataTracking"])
- self.server.runCommand(["setVarFile", var, val, default_file, "earlyAssign"])
- self.runCommand(["disableDataTracking"])
-
- def remove_var_from_file(self, var):
- self.server.runCommand(["removeVarFile", var])
-
- def append_var_in_file(self, var, val, default_file=None):
- self.server.runCommand(["setVarFile", var, val, default_file, "append"])
-
- def append_to_bbfiles(self, val):
- bbfiles = self.runCommand(["getVariable", "BBFILES", "False"]) or ""
- bbfiles = bbfiles.split()
- if val not in bbfiles:
- self.append_var_in_file("BBFILES", val, "bblayers.conf")
-
- def get_parameters(self):
- # retrieve the parameters from bitbake
- params = {}
- params["core_base"] = self.runCommand(["getVariable", "COREBASE"]) or ""
- params["layer"] = self.runCommand(["getVariable", "BBLAYERS"]) or ""
- params["layers_non_removable"] = self.runCommand(["getVariable", "BBLAYERS_NON_REMOVABLE"]) or ""
- params["dldir"] = self.runCommand(["getVariable", "DL_DIR"]) or ""
- params["machine"] = self.runCommand(["getVariable", "MACHINE"]) or ""
- params["distro"] = self.runCommand(["getVariable", "DISTRO"]) or "defaultsetup"
- params["pclass"] = self.runCommand(["getVariable", "PACKAGE_CLASSES"]) or ""
- params["sstatedir"] = self.runCommand(["getVariable", "SSTATE_DIR"]) or ""
- params["sstatemirror"] = self.runCommand(["getVariable", "SSTATE_MIRRORS"]) or ""
-
- num_threads = self.runCommand(["getCpuCount"])
- if not num_threads:
- num_threads = 1
- max_threads = 65536
- else:
- try:
- num_threads = int(num_threads)
- max_threads = 16 * num_threads
- except:
- num_threads = 1
- max_threads = 65536
- params["max_threads"] = max_threads
-
- bbthread = self.runCommand(["getVariable", "BB_NUMBER_THREADS"])
- if not bbthread:
- bbthread = num_threads
- else:
- try:
- bbthread = int(bbthread)
- except:
- bbthread = num_threads
- params["bbthread"] = bbthread
-
- pmake = self.runCommand(["getVariable", "PARALLEL_MAKE"])
- if not pmake:
- pmake = num_threads
- elif isinstance(pmake, int):
- pass
- else:
- try:
- pmake = int(pmake.lstrip("-j "))
- except:
- pmake = num_threads
- params["pmake"] = "-j %s" % pmake
-
- params["image_addr"] = self.runCommand(["getVariable", "DEPLOY_DIR_IMAGE"]) or ""
-
- image_extra_size = self.runCommand(["getVariable", "IMAGE_ROOTFS_EXTRA_SPACE"])
- if not image_extra_size:
- image_extra_size = 0
- else:
- try:
- image_extra_size = int(image_extra_size)
- except:
- image_extra_size = 0
- params["image_extra_size"] = image_extra_size
-
- image_rootfs_size = self.runCommand(["getVariable", "IMAGE_ROOTFS_SIZE"])
- if not image_rootfs_size:
- image_rootfs_size = 0
- else:
- try:
- image_rootfs_size = int(image_rootfs_size)
- except:
- image_rootfs_size = 0
- params["image_rootfs_size"] = image_rootfs_size
-
- image_overhead_factor = self.runCommand(["getVariable", "IMAGE_OVERHEAD_FACTOR"])
- if not image_overhead_factor:
- image_overhead_factor = 1
- else:
- try:
- image_overhead_factor = float(image_overhead_factor)
- except:
- image_overhead_factor = 1
- params['image_overhead_factor'] = image_overhead_factor
-
- params["incompat_license"] = self._remove_redundant(self.runCommand(["getVariable", "INCOMPATIBLE_LICENSE"]) or "")
- params["sdk_machine"] = self.runCommand(["getVariable", "SDKMACHINE"]) or self.runCommand(["getVariable", "SDK_ARCH"]) or ""
-
- params["image_fstypes"] = self._remove_redundant(self.runCommand(["getVariable", "IMAGE_FSTYPES"]) or "")
-
- params["image_types"] = self._remove_redundant(self.runCommand(["getVariable", "IMAGE_TYPES"]) or "")
-
- params["conf_version"] = self.runCommand(["getVariable", "CONF_VERSION"]) or ""
- params["lconf_version"] = self.runCommand(["getVariable", "LCONF_VERSION"]) or ""
-
- params["runnable_image_types"] = self._remove_redundant(self.runCommand(["getVariable", "RUNNABLE_IMAGE_TYPES"]) or "")
- params["runnable_machine_patterns"] = self._remove_redundant(self.runCommand(["getVariable", "RUNNABLE_MACHINE_PATTERNS"]) or "")
- params["deployable_image_types"] = self._remove_redundant(self.runCommand(["getVariable", "DEPLOYABLE_IMAGE_TYPES"]) or "")
- params["kernel_image_type"] = self.runCommand(["getVariable", "KERNEL_IMAGETYPE"]) or ""
- params["tmpdir"] = self.runCommand(["getVariable", "TMPDIR"]) or ""
- params["distro_version"] = self.runCommand(["getVariable", "DISTRO_VERSION"]) or ""
- params["target_os"] = self.runCommand(["getVariable", "TARGET_OS"]) or ""
- params["target_arch"] = self.runCommand(["getVariable", "TARGET_ARCH"]) or ""
- params["tune_pkgarch"] = self.runCommand(["getVariable", "TUNE_PKGARCH"]) or ""
- params["bb_version"] = self.runCommand(["getVariable", "BB_MIN_VERSION"]) or ""
-
- params["default_task"] = self.runCommand(["getVariable", "BB_DEFAULT_TASK"]) or "build"
-
- params["socks_proxy"] = self.runCommand(["getVariable", "all_proxy"]) or ""
- params["http_proxy"] = self.runCommand(["getVariable", "http_proxy"]) or ""
- params["ftp_proxy"] = self.runCommand(["getVariable", "ftp_proxy"]) or ""
- params["https_proxy"] = self.runCommand(["getVariable", "https_proxy"]) or ""
-
- params["cvs_proxy_host"] = self.runCommand(["getVariable", "CVS_PROXY_HOST"]) or ""
- params["cvs_proxy_port"] = self.runCommand(["getVariable", "CVS_PROXY_PORT"]) or ""
-
- params["image_white_pattern"] = self.runCommand(["getVariable", "BBUI_IMAGE_WHITE_PATTERN"]) or ""
- params["image_black_pattern"] = self.runCommand(["getVariable", "BBUI_IMAGE_BLACK_PATTERN"]) or ""
- return params
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/hoblistmodel.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/hoblistmodel.py
deleted file mode 100644
index 50df156f4..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/hoblistmodel.py
+++ /dev/null
@@ -1,903 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2011 Intel Corporation
-#
-# Authored by Joshua Lock <josh@linux.intel.com>
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import gtk
-import gobject
-from bb.ui.crumbs.hobpages import HobPage
-
-#
-# PackageListModel
-#
-class PackageListModel(gtk.ListStore):
- """
- This class defines an gtk.ListStore subclass which will convert the output
- of the bb.event.TargetsTreeGenerated event into a gtk.ListStore whilst also
- providing convenience functions to access gtk.TreeModel subclasses which
- provide filtered views of the data.
- """
-
- (COL_NAME, COL_VER, COL_REV, COL_RNM, COL_SEC, COL_SUM, COL_RDEP, COL_RPROV, COL_SIZE, COL_RCP, COL_BINB, COL_INC, COL_FADE_INC, COL_FONT, COL_FLIST) = range(15)
-
- __gsignals__ = {
- "package-selection-changed" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- }
-
- __toolchain_required_packages__ = ["packagegroup-core-standalone-sdk-target", "packagegroup-core-standalone-sdk-target-dbg"]
-
- def __init__(self):
- self.rprov_pkg = {}
- gtk.ListStore.__init__ (self,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_BOOLEAN,
- gobject.TYPE_BOOLEAN,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING)
- self.sort_column_id, self.sort_order = PackageListModel.COL_NAME, gtk.SORT_ASCENDING
-
- """
- Find the model path for the item_name
- Returns the path in the model or None
- """
- def find_path_for_item(self, item_name):
- pkg = item_name
- if item_name not in self.pn_path.keys():
- if item_name not in self.rprov_pkg.keys():
- return None
- pkg = self.rprov_pkg[item_name]
- if pkg not in self.pn_path.keys():
- return None
-
- return self.pn_path[pkg]
-
- def find_item_for_path(self, item_path):
- return self[item_path][self.COL_NAME]
-
- """
- Helper function to determine whether an item is an item specified by filter
- """
- def tree_model_filter(self, model, it, filter):
- name = model.get_value(it, self.COL_NAME)
-
- for key in filter.keys():
- if key == self.COL_NAME:
- if filter[key] != 'Search packages by name':
- if name and filter[key] not in name:
- return False
- else:
- if model.get_value(it, key) not in filter[key]:
- return False
- self.filtered_nb += 1
- return True
-
- """
- Create, if required, and return a filtered gtk.TreeModelSort
- containing only the items specified by filter
- """
- def tree_model(self, filter, excluded_items_ahead=False, included_items_ahead=False, search_data=None, initial=False):
- model = self.filter_new()
- self.filtered_nb = 0
- model.set_visible_func(self.tree_model_filter, filter)
-
- sort = gtk.TreeModelSort(model)
- sort.connect ('sort-column-changed', self.sort_column_changed_cb)
- if initial:
- sort.set_sort_column_id(PackageListModel.COL_NAME, gtk.SORT_ASCENDING)
- sort.set_default_sort_func(None)
- elif excluded_items_ahead:
- sort.set_default_sort_func(self.exclude_item_sort_func, search_data)
- elif included_items_ahead:
- sort.set_default_sort_func(self.include_item_sort_func, search_data)
- else:
- if search_data and search_data!='Search recipes by name' and search_data!='Search package groups by name':
- sort.set_default_sort_func(self.sort_func, search_data)
- else:
- sort.set_sort_column_id(self.sort_column_id, self.sort_order)
- sort.set_default_sort_func(None)
-
- sort.set_sort_func(PackageListModel.COL_INC, self.sort_column, PackageListModel.COL_INC)
- sort.set_sort_func(PackageListModel.COL_SIZE, self.sort_column, PackageListModel.COL_SIZE)
- sort.set_sort_func(PackageListModel.COL_BINB, self.sort_binb_column)
- sort.set_sort_func(PackageListModel.COL_RCP, self.sort_column, PackageListModel.COL_RCP)
- return sort
-
- def sort_column_changed_cb (self, data):
- self.sort_column_id, self.sort_order = data.get_sort_column_id ()
-
- def sort_column(self, model, row1, row2, col):
- value1 = model.get_value(row1, col)
- value2 = model.get_value(row2, col)
- if col==PackageListModel.COL_SIZE:
- value1 = HobPage._string_to_size(value1)
- value2 = HobPage._string_to_size(value2)
-
- cmp_res = cmp(value1, value2)
- if cmp_res!=0:
- if col==PackageListModel.COL_INC:
- return -cmp_res
- else:
- return cmp_res
- else:
- name1 = model.get_value(row1, PackageListModel.COL_NAME)
- name2 = model.get_value(row2, PackageListModel.COL_NAME)
- return cmp(name1,name2)
-
- def sort_binb_column(self, model, row1, row2):
- value1 = model.get_value(row1, PackageListModel.COL_BINB)
- value2 = model.get_value(row2, PackageListModel.COL_BINB)
- value1_list = value1.split(', ')
- value2_list = value2.split(', ')
-
- value1 = value1_list[0]
- value2 = value2_list[0]
-
- cmp_res = cmp(value1, value2)
- if cmp_res==0:
- cmp_size = cmp(len(value1_list), len(value2_list))
- if cmp_size==0:
- name1 = model.get_value(row1, PackageListModel.COL_NAME)
- name2 = model.get_value(row2, PackageListModel.COL_NAME)
- return cmp(name1,name2)
- else:
- return cmp_size
- else:
- return cmp_res
-
- def exclude_item_sort_func(self, model, iter1, iter2, user_data=None):
- if user_data:
- val1 = model.get_value(iter1, PackageListModel.COL_NAME)
- val2 = model.get_value(iter2, PackageListModel.COL_NAME)
- return self.cmp_vals(val1, val2, user_data)
- else:
- val1 = model.get_value(iter1, PackageListModel.COL_FADE_INC)
- val2 = model.get_value(iter2, PackageListModel.COL_INC)
- return ((val1 == True) and (val2 == False))
-
- def include_item_sort_func(self, model, iter1, iter2, user_data=None):
- if user_data:
- val1 = model.get_value(iter1, PackageListModel.COL_NAME)
- val2 = model.get_value(iter2, PackageListModel.COL_NAME)
- return self.cmp_vals(val1, val2, user_data)
- else:
- val1 = model.get_value(iter1, PackageListModel.COL_INC)
- val2 = model.get_value(iter2, PackageListModel.COL_INC)
- return ((val1 == False) and (val2 == True))
-
- def sort_func(self, model, iter1, iter2, user_data):
- val1 = model.get_value(iter1, PackageListModel.COL_NAME)
- val2 = model.get_value(iter2, PackageListModel.COL_NAME)
- return self.cmp_vals(val1, val2, user_data)
-
- def cmp_vals(self, val1, val2, user_data):
- if val1 is None or val2 is None:
- return 0
- elif val1.startswith(user_data) and not val2.startswith(user_data):
- return -1
- elif not val1.startswith(user_data) and val2.startswith(user_data):
- return 1
- else:
- return cmp(val1, val2)
-
- def convert_vpath_to_path(self, view_model, view_path):
- # view_model is the model sorted
- # get the path of the model filtered
- filtered_model_path = view_model.convert_path_to_child_path(view_path)
- # get the model filtered
- filtered_model = view_model.get_model()
- # get the path of the original model
- path = filtered_model.convert_path_to_child_path(filtered_model_path)
- return path
-
- def convert_path_to_vpath(self, view_model, path):
- it = view_model.get_iter_first()
- while it:
- name = self.find_item_for_path(path)
- view_name = view_model.get_value(it, PackageListModel.COL_NAME)
- if view_name == name:
- view_path = view_model.get_path(it)
- return view_path
- it = view_model.iter_next(it)
- return None
-
- """
- The populate() function takes as input the data from a
- bb.event.PackageInfo event and populates the package list.
- """
- def populate(self, pkginfolist):
- # First clear the model, in case repopulating
- self.clear()
-
- def getpkgvalue(pkgdict, key, pkgname, defaultval = None):
- value = pkgdict.get('%s_%s' % (key, pkgname), None)
- if not value:
- value = pkgdict.get(key, defaultval)
- return value
-
- for pkginfo in pkginfolist:
- pn = pkginfo['PN']
- pv = pkginfo['PV']
- pr = pkginfo['PR']
- pkg = pkginfo['PKG']
- pkgv = getpkgvalue(pkginfo, 'PKGV', pkg)
- pkgr = getpkgvalue(pkginfo, 'PKGR', pkg)
- # PKGSIZE is artificial, will always be overridden with the package name if present
- pkgsize = int(pkginfo.get('PKGSIZE_%s' % pkg, "0"))
- # PKG_%s is the renamed version
- pkg_rename = pkginfo.get('PKG_%s' % pkg, "")
- # The rest may be overridden or not
- section = getpkgvalue(pkginfo, 'SECTION', pkg, "")
- summary = getpkgvalue(pkginfo, 'SUMMARY', pkg, "")
- rdep = getpkgvalue(pkginfo, 'RDEPENDS', pkg, "")
- rrec = getpkgvalue(pkginfo, 'RRECOMMENDS', pkg, "")
- rprov = getpkgvalue(pkginfo, 'RPROVIDES', pkg, "")
- files_list = getpkgvalue(pkginfo, 'FILES_INFO', pkg, "")
- for i in rprov.split():
- self.rprov_pkg[i] = pkg
-
- recipe = pn + '-' + pv + '-' + pr
-
- allow_empty = getpkgvalue(pkginfo, 'ALLOW_EMPTY', pkg, "")
-
- if pkgsize == 0 and not allow_empty:
- continue
-
- size = HobPage._size_to_string(pkgsize)
- self.set(self.append(), self.COL_NAME, pkg, self.COL_VER, pkgv,
- self.COL_REV, pkgr, self.COL_RNM, pkg_rename,
- self.COL_SEC, section, self.COL_SUM, summary,
- self.COL_RDEP, rdep + ' ' + rrec,
- self.COL_RPROV, rprov, self.COL_SIZE, size,
- self.COL_RCP, recipe, self.COL_BINB, "",
- self.COL_INC, False, self.COL_FONT, '10', self.COL_FLIST, files_list)
-
- self.pn_path = {}
- it = self.get_iter_first()
- while it:
- pn = self.get_value(it, self.COL_NAME)
- path = self.get_path(it)
- self.pn_path[pn] = path
- it = self.iter_next(it)
-
- """
- Update the model, send out the notification.
- """
- def selection_change_notification(self):
- self.emit("package-selection-changed")
-
- """
- Check whether the item at item_path is included or not
- """
- def path_included(self, item_path):
- return self[item_path][self.COL_INC]
-
- """
- Add this item, and any of its dependencies, to the image contents
- """
- def include_item(self, item_path, binb=""):
- if self.path_included(item_path):
- return
-
- item_name = self[item_path][self.COL_NAME]
- item_deps = self[item_path][self.COL_RDEP]
-
- self[item_path][self.COL_INC] = True
-
- item_bin = self[item_path][self.COL_BINB].split(', ')
- if binb and not binb in item_bin:
- item_bin.append(binb)
- self[item_path][self.COL_BINB] = ', '.join(item_bin).lstrip(', ')
-
- if item_deps:
- # Ensure all of the items deps are included and, where appropriate,
- # add this item to their COL_BINB
- for dep in item_deps.split(" "):
- if dep.startswith('('):
- continue
- # If the contents model doesn't already contain dep, add it
- dep_path = self.find_path_for_item(dep)
- if not dep_path:
- continue
- dep_included = self.path_included(dep_path)
-
- if dep_included and not dep in item_bin:
- # don't set the COL_BINB to this item if the target is an
- # item in our own COL_BINB
- dep_bin = self[dep_path][self.COL_BINB].split(', ')
- if not item_name in dep_bin:
- dep_bin.append(item_name)
- self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
- elif not dep_included:
- self.include_item(dep_path, binb=item_name)
-
- def exclude_item(self, item_path):
- if not self.path_included(item_path):
- return
-
- self[item_path][self.COL_INC] = False
-
- item_name = self[item_path][self.COL_NAME]
- item_deps = self[item_path][self.COL_RDEP]
- if item_deps:
- for dep in item_deps.split(" "):
- if dep.startswith('('):
- continue
- dep_path = self.find_path_for_item(dep)
- if not dep_path:
- continue
- dep_bin = self[dep_path][self.COL_BINB].split(', ')
- if item_name in dep_bin:
- dep_bin.remove(item_name)
- self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
-
- item_bin = self[item_path][self.COL_BINB].split(', ')
- if item_bin:
- for binb in item_bin:
- binb_path = self.find_path_for_item(binb)
- if not binb_path:
- continue
- self.exclude_item(binb_path)
-
- """
- Empty self.contents by setting the include of each entry to None
- """
- def reset(self):
- it = self.get_iter_first()
- while it:
- self.set(it,
- self.COL_INC, False,
- self.COL_BINB, "")
- it = self.iter_next(it)
-
- self.selection_change_notification()
-
- def get_selected_packages(self):
- packagelist = []
-
- it = self.get_iter_first()
- while it:
- if self.get_value(it, self.COL_INC):
- name = self.get_value(it, self.COL_NAME)
- packagelist.append(name)
- it = self.iter_next(it)
-
- return packagelist
-
- def get_user_selected_packages(self):
- packagelist = []
-
- it = self.get_iter_first()
- while it:
- if self.get_value(it, self.COL_INC):
- binb = self.get_value(it, self.COL_BINB)
- if binb == "User Selected":
- name = self.get_value(it, self.COL_NAME)
- packagelist.append(name)
- it = self.iter_next(it)
-
- return packagelist
-
- def get_selected_packages_toolchain(self):
- packagelist = []
-
- it = self.get_iter_first()
- while it:
- if self.get_value(it, self.COL_INC):
- name = self.get_value(it, self.COL_NAME)
- if name.endswith("-dev") or name.endswith("-dbg"):
- packagelist.append(name)
- it = self.iter_next(it)
-
- return list(set(packagelist + self.__toolchain_required_packages__));
-
- """
- Package model may be incomplete, therefore when calling the
- set_selected_packages(), some packages will not be set included.
- Return the un-set packages list.
- """
- def set_selected_packages(self, packagelist, user_selected=False):
- left = []
- binb = 'User Selected' if user_selected else ''
- for pn in packagelist:
- if pn in self.pn_path.keys():
- path = self.pn_path[pn]
- self.include_item(item_path=path, binb=binb)
- else:
- left.append(pn)
-
- self.selection_change_notification()
- return left
-
- """
- Return the selected package size, unit is B.
- """
- def get_packages_size(self):
- packages_size = 0
- it = self.get_iter_first()
- while it:
- if self.get_value(it, self.COL_INC):
- str_size = self.get_value(it, self.COL_SIZE)
- if not str_size:
- continue
-
- packages_size += HobPage._string_to_size(str_size)
-
- it = self.iter_next(it)
- return packages_size
-
- """
- Resync the state of included items to a backup column before performing the fadeout visible effect
- """
- def resync_fadeout_column(self, model_first_iter=None):
- it = model_first_iter
- while it:
- active = self.get_value(it, self.COL_INC)
- self.set(it, self.COL_FADE_INC, active)
- it = self.iter_next(it)
-
-#
-# RecipeListModel
-#
-class RecipeListModel(gtk.ListStore):
- """
- This class defines an gtk.ListStore subclass which will convert the output
- of the bb.event.TargetsTreeGenerated event into a gtk.ListStore whilst also
- providing convenience functions to access gtk.TreeModel subclasses which
- provide filtered views of the data.
- """
- (COL_NAME, COL_DESC, COL_LIC, COL_GROUP, COL_DEPS, COL_BINB, COL_TYPE, COL_INC, COL_IMG, COL_INSTALL, COL_PN, COL_FADE_INC, COL_SUMMARY, COL_VERSION,
- COL_REVISION, COL_HOMEPAGE, COL_BUGTRACKER, COL_FILE) = range(18)
-
- __custom_image__ = "Start with an empty image recipe"
-
- __gsignals__ = {
- "recipe-selection-changed" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- }
-
- """
- """
- def __init__(self):
- gtk.ListStore.__init__ (self,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_BOOLEAN,
- gobject.TYPE_BOOLEAN,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_BOOLEAN,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING)
- self.sort_column_id, self.sort_order = RecipeListModel.COL_NAME, gtk.SORT_ASCENDING
-
- """
- Find the model path for the item_name
- Returns the path in the model or None
- """
- def find_path_for_item(self, item_name):
- if self.non_target_name(item_name) or item_name not in self.pn_path.keys():
- return None
- else:
- return self.pn_path[item_name]
-
- def find_item_for_path(self, item_path):
- return self[item_path][self.COL_NAME]
-
- """
- Helper method to determine whether name is a target pn
- """
- def non_target_name(self, name):
- if name and ('-native' in name):
- return True
- return False
-
- """
- Helper function to determine whether an item is an item specified by filter
- """
- def tree_model_filter(self, model, it, filter):
- name = model.get_value(it, self.COL_NAME)
- if self.non_target_name(name):
- return False
-
- for key in filter.keys():
- if key == self.COL_NAME:
- if filter[key] != 'Search recipes by name' and filter[key] != 'Search package groups by name':
- if filter[key] not in name:
- return False
- else:
- if model.get_value(it, key) not in filter[key]:
- return False
- self.filtered_nb += 1
-
- return True
-
- def exclude_item_sort_func(self, model, iter1, iter2, user_data=None):
- if user_data:
- val1 = model.get_value(iter1, RecipeListModel.COL_NAME)
- val2 = model.get_value(iter2, RecipeListModel.COL_NAME)
- return self.cmp_vals(val1, val2, user_data)
- else:
- val1 = model.get_value(iter1, RecipeListModel.COL_FADE_INC)
- val2 = model.get_value(iter2, RecipeListModel.COL_INC)
- return ((val1 == True) and (val2 == False))
-
- def include_item_sort_func(self, model, iter1, iter2, user_data=None):
- if user_data:
- val1 = model.get_value(iter1, RecipeListModel.COL_NAME)
- val2 = model.get_value(iter2, RecipeListModel.COL_NAME)
- return self.cmp_vals(val1, val2, user_data)
- else:
- val1 = model.get_value(iter1, RecipeListModel.COL_INC)
- val2 = model.get_value(iter2, RecipeListModel.COL_INC)
- return ((val1 == False) and (val2 == True))
-
- def sort_func(self, model, iter1, iter2, user_data):
- val1 = model.get_value(iter1, RecipeListModel.COL_NAME)
- val2 = model.get_value(iter2, RecipeListModel.COL_NAME)
- return self.cmp_vals(val1, val2, user_data)
-
- def cmp_vals(self, val1, val2, user_data):
- if val1 is None or val2 is None:
- return 0
- elif val1.startswith(user_data) and not val2.startswith(user_data):
- return -1
- elif not val1.startswith(user_data) and val2.startswith(user_data):
- return 1
- else:
- return cmp(val1, val2)
-
- """
- Create, if required, and return a filtered gtk.TreeModelSort
- containing only the items specified by filter
- """
- def tree_model(self, filter, excluded_items_ahead=False, included_items_ahead=False, search_data=None, initial=False):
- model = self.filter_new()
- self.filtered_nb = 0
- model.set_visible_func(self.tree_model_filter, filter)
-
- sort = gtk.TreeModelSort(model)
- sort.connect ('sort-column-changed', self.sort_column_changed_cb)
- if initial:
- sort.set_sort_column_id(RecipeListModel.COL_NAME, gtk.SORT_ASCENDING)
- sort.set_default_sort_func(None)
- elif excluded_items_ahead:
- sort.set_default_sort_func(self.exclude_item_sort_func, search_data)
- elif included_items_ahead:
- sort.set_default_sort_func(self.include_item_sort_func, search_data)
- else:
- if search_data and search_data!='Search recipes by name' and search_data!='Search package groups by name':
- sort.set_default_sort_func(self.sort_func, search_data)
- else:
- sort.set_sort_column_id(self.sort_column_id, self.sort_order)
- sort.set_default_sort_func(None)
-
- sort.set_sort_func(RecipeListModel.COL_INC, self.sort_column, RecipeListModel.COL_INC)
- sort.set_sort_func(RecipeListModel.COL_GROUP, self.sort_column, RecipeListModel.COL_GROUP)
- sort.set_sort_func(RecipeListModel.COL_BINB, self.sort_binb_column)
- sort.set_sort_func(RecipeListModel.COL_LIC, self.sort_column, RecipeListModel.COL_LIC)
- return sort
-
- def sort_column_changed_cb (self, data):
- self.sort_column_id, self.sort_order = data.get_sort_column_id ()
-
- def sort_column(self, model, row1, row2, col):
- value1 = model.get_value(row1, col)
- value2 = model.get_value(row2, col)
- cmp_res = cmp(value1, value2)
- if cmp_res!=0:
- if col==RecipeListModel.COL_INC:
- return -cmp_res
- else:
- return cmp_res
- else:
- name1 = model.get_value(row1, RecipeListModel.COL_NAME)
- name2 = model.get_value(row2, RecipeListModel.COL_NAME)
- return cmp(name1,name2)
-
- def sort_binb_column(self, model, row1, row2):
- value1 = model.get_value(row1, RecipeListModel.COL_BINB)
- value2 = model.get_value(row2, RecipeListModel.COL_BINB)
- value1_list = value1.split(', ')
- value2_list = value2.split(', ')
-
- value1 = value1_list[0]
- value2 = value2_list[0]
-
- cmp_res = cmp(value1, value2)
- if cmp_res==0:
- cmp_size = cmp(len(value1_list), len(value2_list))
- if cmp_size==0:
- name1 = model.get_value(row1, RecipeListModel.COL_NAME)
- name2 = model.get_value(row2, RecipeListModel.COL_NAME)
- return cmp(name1,name2)
- else:
- return cmp_size
- else:
- return cmp_res
-
- def convert_vpath_to_path(self, view_model, view_path):
- filtered_model_path = view_model.convert_path_to_child_path(view_path)
- filtered_model = view_model.get_model()
-
- # get the path of the original model
- path = filtered_model.convert_path_to_child_path(filtered_model_path)
- return path
-
- def convert_path_to_vpath(self, view_model, path):
- it = view_model.get_iter_first()
- while it:
- name = self.find_item_for_path(path)
- view_name = view_model.get_value(it, RecipeListModel.COL_NAME)
- if view_name == name:
- view_path = view_model.get_path(it)
- return view_path
- it = view_model.iter_next(it)
- return None
-
- """
- The populate() function takes as input the data from a
- bb.event.TargetsTreeGenerated event and populates the RecipeList.
- """
- def populate(self, event_model):
- # First clear the model, in case repopulating
- self.clear()
-
- # dummy image for prompt
- self.set_in_list(self.__custom_image__, "Use 'Edit image recipe' to customize recipes and packages " \
- "to be included in your image ")
-
- for item in event_model["pn"]:
- name = item
- desc = event_model["pn"][item]["description"]
- lic = event_model["pn"][item]["license"]
- group = event_model["pn"][item]["section"]
- inherits = event_model["pn"][item]["inherits"]
- summary = event_model["pn"][item]["summary"]
- version = event_model["pn"][item]["version"]
- revision = event_model["pn"][item]["prevision"]
- homepage = event_model["pn"][item]["homepage"]
- bugtracker = event_model["pn"][item]["bugtracker"]
- filename = event_model["pn"][item]["filename"]
- install = []
-
- depends = event_model["depends"].get(item, []) + event_model["rdepends-pn"].get(item, [])
-
- if ('packagegroup.bbclass' in " ".join(inherits)):
- atype = 'packagegroup'
- elif ('/image.bbclass' in " ".join(inherits)):
- if "edited" not in name:
- atype = 'image'
- install = event_model["rdepends-pkg"].get(item, []) + event_model["rrecs-pkg"].get(item, [])
- elif ('meta-' in name):
- atype = 'toolchain'
- elif (name == 'dummy-image' or name == 'dummy-toolchain'):
- atype = 'dummy'
- else:
- atype = 'recipe'
-
- self.set(self.append(), self.COL_NAME, item, self.COL_DESC, desc,
- self.COL_LIC, lic, self.COL_GROUP, group,
- self.COL_DEPS, " ".join(depends), self.COL_BINB, "",
- self.COL_TYPE, atype, self.COL_INC, False,
- self.COL_IMG, False, self.COL_INSTALL, " ".join(install), self.COL_PN, item,
- self.COL_SUMMARY, summary, self.COL_VERSION, version, self.COL_REVISION, revision,
- self.COL_HOMEPAGE, homepage, self.COL_BUGTRACKER, bugtracker,
- self.COL_FILE, filename)
-
- self.pn_path = {}
- it = self.get_iter_first()
- while it:
- pn = self.get_value(it, self.COL_NAME)
- path = self.get_path(it)
- self.pn_path[pn] = path
- it = self.iter_next(it)
-
- def set_in_list(self, item, desc):
- self.set(self.append(), self.COL_NAME, item,
- self.COL_DESC, desc,
- self.COL_LIC, "", self.COL_GROUP, "",
- self.COL_DEPS, "", self.COL_BINB, "",
- self.COL_TYPE, "image", self.COL_INC, False,
- self.COL_IMG, False, self.COL_INSTALL, "", self.COL_PN, item,
- self.COL_SUMMARY, "", self.COL_VERSION, "", self.COL_REVISION, "",
- self.COL_HOMEPAGE, "", self.COL_BUGTRACKER, "")
- self.pn_path = {}
- it = self.get_iter_first()
- while it:
- pn = self.get_value(it, self.COL_NAME)
- path = self.get_path(it)
- self.pn_path[pn] = path
- it = self.iter_next(it)
-
- """
- Update the model, send out the notification.
- """
- def selection_change_notification(self):
- self.emit("recipe-selection-changed")
-
- def path_included(self, item_path):
- return self[item_path][self.COL_INC]
-
- """
- Add this item, and any of its dependencies, to the image contents
- """
- def include_item(self, item_path, binb="", image_contents=False):
- if self.path_included(item_path):
- return
-
- item_name = self[item_path][self.COL_NAME]
- item_deps = self[item_path][self.COL_DEPS]
-
- self[item_path][self.COL_INC] = True
-
- item_bin = self[item_path][self.COL_BINB].split(', ')
- if binb and not binb in item_bin:
- item_bin.append(binb)
- self[item_path][self.COL_BINB] = ', '.join(item_bin).lstrip(', ')
-
- # We want to do some magic with things which are brought in by the
- # base image so tag them as so
- if image_contents:
- self[item_path][self.COL_IMG] = True
-
- if item_deps:
- # Ensure all of the items deps are included and, where appropriate,
- # add this item to their COL_BINB
- for dep in item_deps.split(" "):
- # If the contents model doesn't already contain dep, add it
- dep_path = self.find_path_for_item(dep)
- if not dep_path:
- continue
- dep_included = self.path_included(dep_path)
-
- if dep_included and not dep in item_bin:
- # don't set the COL_BINB to this item if the target is an
- # item in our own COL_BINB
- dep_bin = self[dep_path][self.COL_BINB].split(', ')
- if not item_name in dep_bin:
- dep_bin.append(item_name)
- self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
- elif not dep_included:
- self.include_item(dep_path, binb=item_name, image_contents=image_contents)
- dep_bin = self[item_path][self.COL_BINB].split(', ')
- if self[item_path][self.COL_NAME] in dep_bin:
- dep_bin.remove(self[item_path][self.COL_NAME])
- self[item_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
-
- def exclude_item(self, item_path):
- if not self.path_included(item_path):
- return
-
- self[item_path][self.COL_INC] = False
-
- item_name = self[item_path][self.COL_NAME]
- item_deps = self[item_path][self.COL_DEPS]
- if item_deps:
- for dep in item_deps.split(" "):
- dep_path = self.find_path_for_item(dep)
- if not dep_path:
- continue
- dep_bin = self[dep_path][self.COL_BINB].split(', ')
- if item_name in dep_bin:
- dep_bin.remove(item_name)
- self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
-
- item_bin = self[item_path][self.COL_BINB].split(', ')
- if item_bin:
- for binb in item_bin:
- binb_path = self.find_path_for_item(binb)
- if not binb_path:
- continue
- self.exclude_item(binb_path)
-
- def reset(self):
- it = self.get_iter_first()
- while it:
- self.set(it,
- self.COL_INC, False,
- self.COL_BINB, "",
- self.COL_IMG, False)
- it = self.iter_next(it)
-
- self.selection_change_notification()
-
- """
- Returns two lists. One of user selected recipes and the other containing
- all selected recipes
- """
- def get_selected_recipes(self):
- allrecipes = []
- userrecipes = []
-
- it = self.get_iter_first()
- while it:
- if self.get_value(it, self.COL_INC):
- name = self.get_value(it, self.COL_PN)
- type = self.get_value(it, self.COL_TYPE)
- if type != "image":
- allrecipes.append(name)
- sel = "User Selected" in self.get_value(it, self.COL_BINB)
- if sel:
- userrecipes.append(name)
- it = self.iter_next(it)
-
- return list(set(userrecipes)), list(set(allrecipes))
-
- def set_selected_recipes(self, recipelist):
- for pn in recipelist:
- if pn in self.pn_path.keys():
- path = self.pn_path[pn]
- self.include_item(item_path=path,
- binb="User Selected")
- self.selection_change_notification()
-
- def get_selected_image(self):
- it = self.get_iter_first()
- while it:
- if self.get_value(it, self.COL_INC):
- name = self.get_value(it, self.COL_PN)
- type = self.get_value(it, self.COL_TYPE)
- if type == "image":
- sel = "User Selected" in self.get_value(it, self.COL_BINB)
- if sel:
- return name
- it = self.iter_next(it)
- return None
-
- def set_selected_image(self, img):
- if not img:
- return
- self.reset()
- path = self.find_path_for_item(img)
- self.include_item(item_path=path,
- binb="User Selected",
- image_contents=True)
- self.selection_change_notification()
-
- def set_custom_image_version(self, version):
- self.custom_image_version = version
-
- def get_custom_image_version(self):
- return self.custom_image_version
-
- def is_custom_image(self):
- return self.get_selected_image() == self.__custom_image__
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/hobpages.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/hobpages.py
deleted file mode 100755
index 0fd3598c3..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/hobpages.py
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/usr/bin/env python
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2012 Intel Corporation
-#
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import gtk
-from bb.ui.crumbs.hobcolor import HobColors
-from bb.ui.crumbs.hobwidget import hwc
-
-#
-# HobPage: the super class for all Hob-related pages
-#
-class HobPage (gtk.VBox):
-
- def __init__(self, builder, title = None):
- super(HobPage, self).__init__(False, 0)
- self.builder = builder
- self.builder_width, self.builder_height = self.builder.size_request()
-
- if not title:
- self.title = "Hob -- Image Creator"
- else:
- self.title = title
- self.title_label = gtk.Label()
-
- self.box_group_area = gtk.VBox(False, 12)
- self.box_group_area.set_size_request(self.builder_width - 73 - 73, self.builder_height - 88 - 15 - 15)
- self.group_align = gtk.Alignment(xalign = 0, yalign=0.5, xscale=1, yscale=1)
- self.group_align.set_padding(15, 15, 73, 73)
- self.group_align.add(self.box_group_area)
- self.box_group_area.set_homogeneous(False)
-
- def set_title(self, title):
- self.title = title
- self.title_label.set_markup("<span size='x-large'>%s</span>" % self.title)
-
- def add_onto_top_bar(self, widget = None, padding = 0):
- # the top button occupies 1/7 of the page height
- # setup an event box
- eventbox = gtk.EventBox()
- style = eventbox.get_style().copy()
- style.bg[gtk.STATE_NORMAL] = eventbox.get_colormap().alloc_color(HobColors.LIGHT_GRAY, False, False)
- eventbox.set_style(style)
- eventbox.set_size_request(-1, 88)
-
- hbox = gtk.HBox()
-
- self.title_label = gtk.Label()
- self.title_label.set_markup("<span size='x-large'>%s</span>" % self.title)
- hbox.pack_start(self.title_label, expand=False, fill=False, padding=20)
-
- if widget:
- # add the widget in the event box
- hbox.pack_end(widget, expand=False, fill=False, padding=padding)
- eventbox.add(hbox)
-
- return eventbox
-
- def span_tag(self, size="medium", weight="normal", forground="#1c1c1c"):
- span_tag = "weight='%s' foreground='%s' size='%s'" % (weight, forground, size)
- return span_tag
-
- def append_toolbar_button(self, toolbar, buttonname, icon_disp, icon_hovor, tip, cb):
- # Create a button and append it on the toolbar according to button name
- icon = gtk.Image()
- icon_display = icon_disp
- icon_hover = icon_hovor
- pix_buffer = gtk.gdk.pixbuf_new_from_file(icon_display)
- icon.set_from_pixbuf(pix_buffer)
- tip_text = tip
- button = toolbar.append_item(buttonname, tip, None, icon, cb)
- return button
-
- @staticmethod
- def _size_to_string(size):
- try:
- if not size:
- size_str = "0 B"
- else:
- if len(str(int(size))) > 6:
- size_str = '%.1f' % (size*1.0/(1024*1024)) + ' MB'
- elif len(str(int(size))) > 3:
- size_str = '%.1f' % (size*1.0/1024) + ' KB'
- else:
- size_str = str(size) + ' B'
- except:
- size_str = "0 B"
- return size_str
-
- @staticmethod
- def _string_to_size(str_size):
- try:
- if not str_size:
- size = 0
- else:
- unit = str_size.split()
- if len(unit) > 1:
- if unit[1] == 'MB':
- size = float(unit[0])*1024*1024
- elif unit[1] == 'KB':
- size = float(unit[0])*1024
- elif unit[1] == 'B':
- size = float(unit[0])
- else:
- size = 0
- else:
- size = float(unit[0])
- except:
- size = 0
- return size
-
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/imageconfigurationpage.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/imageconfigurationpage.py
deleted file mode 100644
index 2766bea8c..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/imageconfigurationpage.py
+++ /dev/null
@@ -1,561 +0,0 @@
-#!/usr/bin/env python
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2012 Intel Corporation
-#
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import gtk
-import glib
-import re
-from bb.ui.crumbs.progressbar import HobProgressBar
-from bb.ui.crumbs.hobcolor import HobColors
-from bb.ui.crumbs.hobwidget import hic, HobImageButton, HobInfoButton, HobAltButton, HobButton
-from bb.ui.crumbs.hoblistmodel import RecipeListModel
-from bb.ui.crumbs.hobpages import HobPage
-from bb.ui.crumbs.hig.retrieveimagedialog import RetrieveImageDialog
-
-#
-# ImageConfigurationPage
-#
-class ImageConfigurationPage (HobPage):
-
- __dummy_machine__ = "--select a machine--"
- __dummy_image__ = "--select an image recipe--"
- __custom_image__ = "Select from my image recipes"
-
- def __init__(self, builder):
- super(ImageConfigurationPage, self).__init__(builder, "Image configuration")
-
- self.image_combo_id = None
- # we use machine_combo_changed_by_manual to identify the machine is changed by code
- # or by manual. If by manual, all user's recipe selection and package selection are
- # cleared.
- self.machine_combo_changed_by_manual = True
- self.stopping = False
- self.warning_shift = 0
- self.custom_image_selected = None
- self.create_visual_elements()
-
- def create_visual_elements(self):
- # create visual elements
- self.toolbar = gtk.Toolbar()
- self.toolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL)
- self.toolbar.set_style(gtk.TOOLBAR_BOTH)
-
- my_images_button = self.append_toolbar_button(self.toolbar,
- "Images",
- hic.ICON_IMAGES_DISPLAY_FILE,
- hic.ICON_IMAGES_HOVER_FILE,
- "Open previously built images",
- self.my_images_button_clicked_cb)
- settings_button = self.append_toolbar_button(self.toolbar,
- "Settings",
- hic.ICON_SETTINGS_DISPLAY_FILE,
- hic.ICON_SETTINGS_HOVER_FILE,
- "View additional build settings",
- self.settings_button_clicked_cb)
-
- self.config_top_button = self.add_onto_top_bar(self.toolbar)
-
- self.gtable = gtk.Table(40, 40, True)
- self.create_config_machine()
- self.create_config_baseimg()
- self.config_build_button = self.create_config_build_button()
-
- def _remove_all_widget(self):
- children = self.gtable.get_children() or []
- for child in children:
- self.gtable.remove(child)
- children = self.box_group_area.get_children() or []
- for child in children:
- self.box_group_area.remove(child)
- children = self.get_children() or []
- for child in children:
- self.remove(child)
-
- def _pack_components(self, pack_config_build_button = False):
- self._remove_all_widget()
- self.pack_start(self.config_top_button, expand=False, fill=False)
- self.pack_start(self.group_align, expand=True, fill=True)
-
- self.box_group_area.pack_start(self.gtable, expand=True, fill=True)
- if pack_config_build_button:
- self.box_group_area.pack_end(self.config_build_button, expand=False, fill=False)
- else:
- box = gtk.HBox(False, 6)
- box.show()
- subbox = gtk.HBox(False, 0)
- subbox.set_size_request(205, 49)
- subbox.show()
- box.add(subbox)
- self.box_group_area.pack_end(box, False, False)
-
- def show_machine(self):
- self.progress_bar.reset()
- self._pack_components(pack_config_build_button = False)
- self.set_config_machine_layout(show_progress_bar = False)
- self.show_all()
-
- def update_progress_bar(self, title, fraction, status=None):
- if self.stopping == False:
- self.progress_bar.update(fraction)
- self.progress_bar.set_text(title)
- self.progress_bar.set_rcstyle(status)
-
- def show_info_populating(self):
- self._pack_components(pack_config_build_button = False)
- self.set_config_machine_layout(show_progress_bar = True)
- self.show_all()
-
- def show_info_populated(self):
- self.progress_bar.reset()
- self._pack_components(pack_config_build_button = False)
- self.set_config_machine_layout(show_progress_bar = False)
- self.set_config_baseimg_layout()
- self.show_all()
-
- def show_baseimg_selected(self):
- self.progress_bar.reset()
- self._pack_components(pack_config_build_button = True)
- self.set_config_machine_layout(show_progress_bar = False)
- self.set_config_baseimg_layout()
- self.show_all()
- if self.builder.recipe_model.get_selected_image() == self.builder.recipe_model.__custom_image__:
- self.just_bake_button.hide()
-
- def add_warnings_bar(self):
- #create the warnings bar shown when recipes parsing generates warnings
- color = HobColors.KHAKI
- warnings_bar = gtk.EventBox()
- warnings_bar.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
- warnings_bar.set_flags(gtk.CAN_DEFAULT)
- warnings_bar.grab_default()
-
- build_stop_tab = gtk.Table(10, 20, True)
- warnings_bar.add(build_stop_tab)
-
- icon = gtk.Image()
- icon_pix_buffer = gtk.gdk.pixbuf_new_from_file(hic.ICON_INDI_ALERT_FILE)
- icon.set_from_pixbuf(icon_pix_buffer)
- build_stop_tab.attach(icon, 0, 2, 0, 10)
-
- label = gtk.Label()
- label.set_alignment(0.0, 0.5)
- warnings_nb = len(self.builder.parsing_warnings)
- if warnings_nb == 1:
- label.set_markup("<span size='x-large'><b>1 recipe parsing warning</b></span>")
- else:
- label.set_markup("<span size='x-large'><b>%s recipe parsing warnings</b></span>" % warnings_nb)
- build_stop_tab.attach(label, 2, 12, 0, 10)
-
- view_warnings_button = HobButton("View warnings")
- view_warnings_button.connect('clicked', self.view_warnings_button_clicked_cb)
- build_stop_tab.attach(view_warnings_button, 15, 19, 1, 9)
-
- return warnings_bar
-
- def disable_warnings_bar(self):
- if self.builder.parsing_warnings:
- if hasattr(self, 'warnings_bar'):
- self.warnings_bar.hide_all()
- self.builder.parsing_warnings = []
-
- def create_config_machine(self):
- self.machine_title = gtk.Label()
- self.machine_title.set_alignment(0.0, 0.5)
- mark = "<span %s>Select a machine</span>" % self.span_tag('x-large', 'bold')
- self.machine_title.set_markup(mark)
-
- self.machine_title_desc = gtk.Label()
- self.machine_title_desc.set_alignment(0.0, 0.5)
- mark = ("<span %s>Your selection is the profile of the target machine for which you"
- " are building the image.\n</span>") % (self.span_tag('medium'))
- self.machine_title_desc.set_markup(mark)
-
- self.machine_combo = gtk.combo_box_new_text()
- self.machine_combo.connect("changed", self.machine_combo_changed_cb)
-
- icon_file = hic.ICON_LAYERS_DISPLAY_FILE
- hover_file = hic.ICON_LAYERS_HOVER_FILE
- self.layer_button = HobImageButton("Layers", "Add support for machines, software, etc.",
- icon_file, hover_file)
- self.layer_button.connect("clicked", self.layer_button_clicked_cb)
-
- markup = "Layers are a powerful mechanism to extend the Yocto Project "
- markup += "with your own functionality.\n"
- markup += "For more on layers, check the <a href=\""
- markup += "http://www.yoctoproject.org/docs/current/dev-manual/"
- markup += "dev-manual.html#understanding-and-using-layers\">reference manual</a>."
- self.layer_info_icon = HobInfoButton("<b>Layers</b>" + "*" + markup, self.get_parent())
- self.progress_bar = HobProgressBar()
- self.stop_button = HobAltButton("Stop")
- self.stop_button.connect("clicked", self.stop_button_clicked_cb)
- self.machine_separator = gtk.HSeparator()
-
- def set_config_machine_layout(self, show_progress_bar = False):
- self.gtable.attach(self.machine_title, 0, 40, 0, 4)
- self.gtable.attach(self.machine_title_desc, 0, 40, 4, 6)
- self.gtable.attach(self.machine_combo, 0, 12, 7, 10)
- self.gtable.attach(self.layer_button, 14, 36, 7, 12)
- self.gtable.attach(self.layer_info_icon, 36, 40, 7, 11)
- if show_progress_bar:
- #self.gtable.attach(self.progress_box, 0, 40, 15, 18)
- self.gtable.attach(self.progress_bar, 0, 37, 15, 18)
- self.gtable.attach(self.stop_button, 37, 40, 15, 18, 0, 0)
- if self.builder.parsing_warnings:
- self.warnings_bar = self.add_warnings_bar()
- self.gtable.attach(self.warnings_bar, 0, 40, 14, 18)
- self.warning_shift = 4
- else:
- self.warning_shift = 0
- self.gtable.attach(self.machine_separator, 0, 40, 13, 14)
-
- def create_config_baseimg(self):
- self.image_title = gtk.Label()
- self.image_title.set_alignment(0, 1.0)
- mark = "<span %s>Select an image recipe</span>" % self.span_tag('x-large', 'bold')
- self.image_title.set_markup(mark)
-
- self.image_title_desc = gtk.Label()
- self.image_title_desc.set_alignment(0, 0.5)
-
- mark = ("<span %s>Image recipes are a starting point for the type of image you want. "
- "You can build them as \n"
- "they are or edit them to suit your needs.\n</span>") % self.span_tag('medium')
- self.image_title_desc.set_markup(mark)
-
- self.image_combo = gtk.combo_box_new_text()
- self.image_combo.set_row_separator_func(self.combo_separator_func, None)
- self.image_combo_id = self.image_combo.connect("changed", self.image_combo_changed_cb)
-
- self.image_desc = gtk.Label()
- self.image_desc.set_alignment(0.0, 0.5)
- self.image_desc.set_size_request(256, -1)
- self.image_desc.set_justify(gtk.JUSTIFY_LEFT)
- self.image_desc.set_line_wrap(True)
-
- # button to view recipes
- icon_file = hic.ICON_RCIPE_DISPLAY_FILE
- hover_file = hic.ICON_RCIPE_HOVER_FILE
- self.view_adv_configuration_button = HobImageButton("Advanced configuration",
- "Select image types, package formats, etc",
- icon_file, hover_file)
- self.view_adv_configuration_button.connect("clicked", self.view_adv_configuration_button_clicked_cb)
-
- self.image_separator = gtk.HSeparator()
-
- def combo_separator_func(self, model, iter, user_data):
- name = model.get_value(iter, 0)
- if name == "--Separator--":
- return True
-
- def set_config_baseimg_layout(self):
- self.gtable.attach(self.image_title, 0, 40, 15+self.warning_shift, 17+self.warning_shift)
- self.gtable.attach(self.image_title_desc, 0, 40, 18+self.warning_shift, 22+self.warning_shift)
- self.gtable.attach(self.image_combo, 0, 12, 23+self.warning_shift, 26+self.warning_shift)
- self.gtable.attach(self.image_desc, 0, 12, 27+self.warning_shift, 33+self.warning_shift)
- self.gtable.attach(self.view_adv_configuration_button, 14, 36, 23+self.warning_shift, 28+self.warning_shift)
- self.gtable.attach(self.image_separator, 0, 40, 35+self.warning_shift, 36+self.warning_shift)
-
- def create_config_build_button(self):
- # Create the "Build packages" and "Build image" buttons at the bottom
- button_box = gtk.HBox(False, 6)
-
- # create button "Build image"
- self.just_bake_button = HobButton("Build image")
- self.just_bake_button.set_tooltip_text("Build the image recipe as it is")
- self.just_bake_button.connect("clicked", self.just_bake_button_clicked_cb)
- button_box.pack_end(self.just_bake_button, expand=False, fill=False)
-
- # create button "Edit image recipe"
- self.edit_image_button = HobAltButton("Edit image recipe")
- self.edit_image_button.set_tooltip_text("Customize the recipes and packages to be included in your image")
- self.edit_image_button.connect("clicked", self.edit_image_button_clicked_cb)
- button_box.pack_end(self.edit_image_button, expand=False, fill=False)
-
- return button_box
-
- def stop_button_clicked_cb(self, button):
- self.stopping = True
- self.progress_bar.set_text("Stopping recipe parsing")
- self.progress_bar.set_rcstyle("stop")
- self.builder.cancel_parse_sync()
-
- def view_warnings_button_clicked_cb(self, button):
- self.builder.show_warning_dialog()
-
- def machine_combo_changed_idle_cb(self):
- self.builder.window.set_cursor(None)
-
- def machine_combo_changed_cb(self, machine_combo):
- self.stopping = False
- self.builder.parsing_warnings = []
- combo_item = machine_combo.get_active_text()
- if not combo_item or combo_item == self.__dummy_machine__:
- return
-
- self.builder.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
- self.builder.wait(0.1) #wait for combo and cursor to update
-
- # remove __dummy_machine__ item from the store list after first user selection
- # because it is no longer valid
- combo_store = machine_combo.get_model()
- if len(combo_store) and (combo_store[0][0] == self.__dummy_machine__):
- machine_combo.remove_text(0)
-
- self.builder.configuration.curr_mach = combo_item
- if self.machine_combo_changed_by_manual:
- self.builder.configuration.clear_selection()
- # reset machine_combo_changed_by_manual
- self.machine_combo_changed_by_manual = True
-
- self.builder.configuration.selected_image = None
-
- # Do reparse recipes
- self.builder.populate_recipe_package_info_async()
-
- glib.idle_add(self.machine_combo_changed_idle_cb)
-
- def update_machine_combo(self):
- self.disable_warnings_bar()
- all_machines = [self.__dummy_machine__] + self.builder.parameters.all_machines
-
- model = self.machine_combo.get_model()
- model.clear()
- for machine in all_machines:
- self.machine_combo.append_text(machine)
- self.machine_combo.set_active(0)
-
- def switch_machine_combo(self):
- self.disable_warnings_bar()
- self.machine_combo_changed_by_manual = False
- model = self.machine_combo.get_model()
- active = 0
- while active < len(model):
- if model[active][0] == self.builder.configuration.curr_mach:
- self.machine_combo.set_active(active)
- return
- active += 1
-
- if model[0][0] != self.__dummy_machine__:
- self.machine_combo.insert_text(0, self.__dummy_machine__)
-
- self.machine_combo.set_active(0)
-
- def update_image_desc(self):
- desc = ""
- selected_image = self.image_combo.get_active_text()
- if selected_image and selected_image in self.builder.recipe_model.pn_path.keys():
- image_path = self.builder.recipe_model.pn_path[selected_image]
- image_iter = self.builder.recipe_model.get_iter(image_path)
- desc = self.builder.recipe_model.get_value(image_iter, self.builder.recipe_model.COL_DESC)
-
- mark = ("<span %s>%s</span>\n") % (self.span_tag('small'), desc)
- self.image_desc.set_markup(mark)
-
- def image_combo_changed_idle_cb(self, selected_image, selected_recipes, selected_packages):
- self.builder.update_recipe_model(selected_image, selected_recipes)
- self.builder.update_package_model(selected_packages)
- self.builder.window_sensitive(True)
-
- def image_combo_changed_cb(self, combo):
- self.builder.window_sensitive(False)
- selected_image = self.image_combo.get_active_text()
- if selected_image == self.__custom_image__:
- topdir = self.builder.get_topdir()
- images_dir = topdir + "/recipes/images/custom/"
- self.builder.ensure_dir(images_dir)
-
- dialog = RetrieveImageDialog(images_dir, "Select from my image recipes",
- self.builder, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
- response = dialog.run()
- if response == gtk.RESPONSE_OK:
- image_name = dialog.get_filename()
- head, tail = os.path.split(image_name)
- selected_image = os.path.splitext(tail)[0]
- self.custom_image_selected = selected_image
- self.update_image_combo(self.builder.recipe_model, selected_image)
- else:
- selected_image = self.__dummy_image__
- self.update_image_combo(self.builder.recipe_model, None)
- dialog.destroy()
- else:
- if self.custom_image_selected:
- self.custom_image_selected = None
- self.update_image_combo(self.builder.recipe_model, selected_image)
-
- if not selected_image or (selected_image == self.__dummy_image__):
- self.builder.window_sensitive(True)
- self.just_bake_button.hide()
- self.edit_image_button.hide()
- return
-
- # remove __dummy_image__ item from the store list after first user selection
- # because it is no longer valid
- combo_store = combo.get_model()
- if len(combo_store) and (combo_store[0][0] == self.__dummy_image__):
- combo.remove_text(0)
-
- self.builder.customized = False
-
- selected_recipes = []
-
- image_path = self.builder.recipe_model.pn_path[selected_image]
- image_iter = self.builder.recipe_model.get_iter(image_path)
- selected_packages = self.builder.recipe_model.get_value(image_iter, self.builder.recipe_model.COL_INSTALL).split()
- self.update_image_desc()
-
- self.builder.recipe_model.reset()
- self.builder.package_model.reset()
-
- self.show_baseimg_selected()
-
- if selected_image == self.builder.recipe_model.__custom_image__:
- self.just_bake_button.hide()
-
- glib.idle_add(self.image_combo_changed_idle_cb, selected_image, selected_recipes, selected_packages)
-
- def _image_combo_connect_signal(self):
- if not self.image_combo_id:
- self.image_combo_id = self.image_combo.connect("changed", self.image_combo_changed_cb)
-
- def _image_combo_disconnect_signal(self):
- if self.image_combo_id:
- self.image_combo.disconnect(self.image_combo_id)
- self.image_combo_id = None
-
- def update_image_combo(self, recipe_model, selected_image):
- # Update the image combo according to the images in the recipe_model
- # populate image combo
- filter = {RecipeListModel.COL_TYPE : ['image']}
- image_model = recipe_model.tree_model(filter)
- image_model.set_sort_column_id(recipe_model.COL_NAME, gtk.SORT_ASCENDING)
- active = 0
- cnt = 0
-
- white_pattern = []
- if self.builder.parameters.image_white_pattern:
- for i in self.builder.parameters.image_white_pattern.split():
- white_pattern.append(re.compile(i))
-
- black_pattern = []
- if self.builder.parameters.image_black_pattern:
- for i in self.builder.parameters.image_black_pattern.split():
- black_pattern.append(re.compile(i))
- black_pattern.append(re.compile("hob-image"))
- black_pattern.append(re.compile("edited(-[0-9]*)*.bb$"))
-
- it = image_model.get_iter_first()
- self._image_combo_disconnect_signal()
- model = self.image_combo.get_model()
- model.clear()
- # Set a indicator text to combo store when first open
- if not selected_image:
- self.image_combo.append_text(self.__dummy_image__)
- cnt = cnt + 1
-
- self.image_combo.append_text(self.__custom_image__)
- self.image_combo.append_text("--Separator--")
- cnt = cnt + 2
-
- topdir = self.builder.get_topdir()
- # append and set active
- while it:
- path = image_model.get_path(it)
- it = image_model.iter_next(it)
- image_name = image_model[path][recipe_model.COL_NAME]
- if image_name == self.builder.recipe_model.__custom_image__:
- continue
-
- if black_pattern:
- allow = True
- for pattern in black_pattern:
- if pattern.search(image_name):
- allow = False
- break
- elif white_pattern:
- allow = False
- for pattern in white_pattern:
- if pattern.search(image_name):
- allow = True
- break
- else:
- allow = True
-
- file_name = image_model[path][recipe_model.COL_FILE]
- if file_name and topdir in file_name:
- allow = False
-
- if allow:
- self.image_combo.append_text(image_name)
- if image_name == selected_image:
- active = cnt
- cnt = cnt + 1
- self.image_combo.append_text(self.builder.recipe_model.__custom_image__)
-
- if selected_image == self.builder.recipe_model.__custom_image__:
- active = cnt
-
- if self.custom_image_selected:
- self.image_combo.append_text("--Separator--")
- self.image_combo.append_text(self.custom_image_selected)
- cnt = cnt + 2
- if self.custom_image_selected == selected_image:
- active = cnt
-
- self.image_combo.set_active(active)
-
- if active != 0:
- self.show_baseimg_selected()
-
- self._image_combo_connect_signal()
-
- def layer_button_clicked_cb(self, button):
- # Create a layer selection dialog
- self.builder.show_layer_selection_dialog()
-
- def view_adv_configuration_button_clicked_cb(self, button):
- # Create an advanced settings dialog
- response, settings_changed = self.builder.show_adv_settings_dialog()
- if not response:
- return
- if settings_changed:
- self.builder.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
- self.builder.wait(0.1) #wait for adv_settings_dialog to terminate
- self.builder.reparse_post_adv_settings()
- self.builder.window.set_cursor(None)
-
- def just_bake_button_clicked_cb(self, button):
- self.builder.parsing_warnings = []
- self.builder.just_bake()
-
- def edit_image_button_clicked_cb(self, button):
- self.builder.set_base_image()
- self.builder.show_recipes()
-
- def my_images_button_clicked_cb(self, button):
- self.builder.show_load_my_images_dialog()
-
- def settings_button_clicked_cb(self, button):
- # Create an advanced settings dialog
- response, settings_changed = self.builder.show_simple_settings_dialog()
- if not response:
- return
- if settings_changed:
- self.builder.reparse_post_adv_settings()
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/imagedetailspage.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/imagedetailspage.py
deleted file mode 100755
index 352e9489f..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/imagedetailspage.py
+++ /dev/null
@@ -1,669 +0,0 @@
-#!/usr/bin/env python
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2012 Intel Corporation
-#
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import gobject
-import gtk
-from bb.ui.crumbs.hobcolor import HobColors
-from bb.ui.crumbs.hobwidget import hic, HobViewTable, HobAltButton, HobButton
-from bb.ui.crumbs.hobpages import HobPage
-import subprocess
-from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
-from bb.ui.crumbs.hig.saveimagedialog import SaveImageDialog
-
-#
-# ImageDetailsPage
-#
-class ImageDetailsPage (HobPage):
-
- class DetailBox (gtk.EventBox):
- def __init__(self, widget = None, varlist = None, vallist = None, icon = None, button = None, button2=None, color = HobColors.LIGHT_GRAY):
- gtk.EventBox.__init__(self)
-
- # set color
- style = self.get_style().copy()
- style.bg[gtk.STATE_NORMAL] = self.get_colormap().alloc_color(color, False, False)
- self.set_style(style)
-
- self.row = gtk.Table(1, 2, False)
- self.row.set_border_width(10)
- self.add(self.row)
-
- total_rows = 0
- if widget:
- total_rows = 10
- if varlist and vallist:
- # pack the icon and the text on the left
- total_rows += len(varlist)
- self.table = gtk.Table(total_rows, 20, True)
- self.table.set_row_spacings(6)
- self.table.set_size_request(100, -1)
- self.row.attach(self.table, 0, 1, 0, 1, xoptions=gtk.FILL|gtk.EXPAND, yoptions=gtk.FILL)
-
- colid = 0
- rowid = 0
- self.line_widgets = {}
- if icon:
- self.table.attach(icon, colid, colid + 2, 0, 1)
- colid = colid + 2
- if widget:
- self.table.attach(widget, colid, 20, 0, 10)
- rowid = 10
- if varlist and vallist:
- for row in range(rowid, total_rows):
- index = row - rowid
- self.line_widgets[varlist[index]] = self.text2label(varlist[index], vallist[index])
- self.table.attach(self.line_widgets[varlist[index]], colid, 20, row, row + 1)
- # pack the button on the right
- if button:
- self.bbox = gtk.VBox()
- self.bbox.pack_start(button, expand=True, fill=False)
- if button2:
- self.bbox.pack_start(button2, expand=True, fill=False)
- self.bbox.set_size_request(150,-1)
- self.row.attach(self.bbox, 1, 2, 0, 1, xoptions=gtk.FILL, yoptions=gtk.EXPAND)
-
- def update_line_widgets(self, variable, value):
- if len(self.line_widgets) == 0:
- return
- if not isinstance(self.line_widgets[variable], gtk.Label):
- return
- self.line_widgets[variable].set_markup(self.format_line(variable, value))
-
- def wrap_line(self, inputs):
- # wrap the long text of inputs
- wrap_width_chars = 75
- outputs = ""
- tmps = inputs
- less_chars = len(inputs)
- while (less_chars - wrap_width_chars) > 0:
- less_chars -= wrap_width_chars
- outputs += tmps[:wrap_width_chars] + "\n "
- tmps = inputs[less_chars:]
- outputs += tmps
- return outputs
-
- def format_line(self, variable, value):
- wraped_value = self.wrap_line(value)
- markup = "<span weight=\'bold\'>%s</span>" % variable
- markup += "<span weight=\'normal\' foreground=\'#1c1c1c\' font_desc=\'14px\'>%s</span>" % wraped_value
- return markup
-
- def text2label(self, variable, value):
- # append the name:value to the left box
- # such as "Name: hob-core-minimal-variant-2011-12-15-beagleboard"
- label = gtk.Label()
- label.set_alignment(0.0, 0.5)
- label.set_markup(self.format_line(variable, value))
- return label
-
- class BuildDetailBox (gtk.EventBox):
- def __init__(self, varlist = None, vallist = None, icon = None, color = HobColors.LIGHT_GRAY):
- gtk.EventBox.__init__(self)
-
- # set color
- style = self.get_style().copy()
- style.bg[gtk.STATE_NORMAL] = self.get_colormap().alloc_color(color, False, False)
- self.set_style(style)
-
- self.hbox = gtk.HBox()
- self.hbox.set_border_width(10)
- self.add(self.hbox)
-
- total_rows = 0
- if varlist and vallist:
- # pack the icon and the text on the left
- total_rows += len(varlist)
- self.table = gtk.Table(total_rows, 20, True)
- self.table.set_row_spacings(6)
- self.table.set_size_request(100, -1)
- self.hbox.pack_start(self.table, expand=True, fill=True, padding=15)
-
- colid = 0
- rowid = 0
- self.line_widgets = {}
- if icon:
- self.table.attach(icon, colid, colid + 2, 0, 1)
- colid = colid + 2
- if varlist and vallist:
- for row in range(rowid, total_rows):
- index = row - rowid
- self.line_widgets[varlist[index]] = self.text2label(varlist[index], vallist[index])
- self.table.attach(self.line_widgets[varlist[index]], colid, 20, row, row + 1)
-
- def update_line_widgets(self, variable, value):
- if len(self.line_widgets) == 0:
- return
- if not isinstance(self.line_widgets[variable], gtk.Label):
- return
- self.line_widgets[variable].set_markup(self.format_line(variable, value))
-
- def wrap_line(self, inputs):
- # wrap the long text of inputs
- wrap_width_chars = 75
- outputs = ""
- tmps = inputs
- less_chars = len(inputs)
- while (less_chars - wrap_width_chars) > 0:
- less_chars -= wrap_width_chars
- outputs += tmps[:wrap_width_chars] + "\n "
- tmps = inputs[less_chars:]
- outputs += tmps
- return outputs
-
- def format_line(self, variable, value):
- wraped_value = self.wrap_line(value)
- markup = "<span weight=\'bold\'>%s</span>" % variable
- markup += "<span weight=\'normal\' foreground=\'#1c1c1c\' font_desc=\'14px\'>%s</span>" % wraped_value
- return markup
-
- def text2label(self, variable, value):
- # append the name:value to the left box
- # such as "Name: hob-core-minimal-variant-2011-12-15-beagleboard"
- label = gtk.Label()
- label.set_alignment(0.0, 0.5)
- label.set_markup(self.format_line(variable, value))
- return label
-
- def __init__(self, builder):
- super(ImageDetailsPage, self).__init__(builder, "Image details")
-
- self.image_store = []
- self.button_ids = {}
- self.details_bottom_buttons = gtk.HBox(False, 6)
- self.image_saved = False
- self.create_visual_elements()
- self.name_field_template = ""
- self.description_field_template = ""
-
- def create_visual_elements(self):
- # create visual elements
- # create the toolbar
- self.toolbar = gtk.Toolbar()
- self.toolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL)
- self.toolbar.set_style(gtk.TOOLBAR_BOTH)
-
- my_images_button = self.append_toolbar_button(self.toolbar,
- "Images",
- hic.ICON_IMAGES_DISPLAY_FILE,
- hic.ICON_IMAGES_HOVER_FILE,
- "Open previously built images",
- self.my_images_button_clicked_cb)
- settings_button = self.append_toolbar_button(self.toolbar,
- "Settings",
- hic.ICON_SETTINGS_DISPLAY_FILE,
- hic.ICON_SETTINGS_HOVER_FILE,
- "View additional build settings",
- self.settings_button_clicked_cb)
-
- self.details_top_buttons = self.add_onto_top_bar(self.toolbar)
-
- def _remove_all_widget(self):
- children = self.get_children() or []
- for child in children:
- self.remove(child)
- children = self.box_group_area.get_children() or []
- for child in children:
- self.box_group_area.remove(child)
- children = self.details_bottom_buttons.get_children() or []
- for child in children:
- self.details_bottom_buttons.remove(child)
-
- def show_page(self, step):
- self.build_succeeded = (step == self.builder.IMAGE_GENERATED)
- image_addr = self.builder.parameters.image_addr
- image_names = self.builder.parameters.image_names
- if self.build_succeeded:
- machine = self.builder.configuration.curr_mach
- base_image = self.builder.recipe_model.get_selected_image()
- layers = self.builder.configuration.layers
- pkg_num = "%s" % len(self.builder.package_model.get_selected_packages())
- log_file = self.builder.current_logfile
- else:
- pkg_num = "N/A"
- log_file = None
-
- # remove
- for button_id, button in self.button_ids.items():
- button.disconnect(button_id)
- self._remove_all_widget()
-
- # repack
- self.pack_start(self.details_top_buttons, expand=False, fill=False)
- self.pack_start(self.group_align, expand=True, fill=True)
-
- self.build_result = None
- if self.image_saved or (self.build_succeeded and self.builder.current_step == self.builder.IMAGE_GENERATING):
- # building is the previous step
- icon = gtk.Image()
- pixmap_path = hic.ICON_INDI_CONFIRM_FILE
- color = HobColors.RUNNING
- pix_buffer = gtk.gdk.pixbuf_new_from_file(pixmap_path)
- icon.set_from_pixbuf(pix_buffer)
- varlist = [""]
- if self.image_saved:
- vallist = ["Your image recipe has been saved"]
- else:
- vallist = ["Your image is ready"]
- self.build_result = self.BuildDetailBox(varlist=varlist, vallist=vallist, icon=icon, color=color)
- self.box_group_area.pack_start(self.build_result, expand=False, fill=False)
-
- self.buttonlist = ["Build new image", "Save image recipe", "Run image", "Deploy image"]
-
- # Name
- self.image_store = []
- self.toggled_image = ""
- default_image_size = 0
- self.num_toggled = 0
- i = 0
- for image_name in image_names:
- image_size = HobPage._size_to_string(os.stat(os.path.join(image_addr, image_name)).st_size)
-
- image_attr = ("run" if (self.test_type_runnable(image_name) and self.test_mach_runnable(image_name)) else \
- ("deploy" if self.test_deployable(image_name) else ""))
- is_toggled = (image_attr != "")
-
- if not self.toggled_image:
- if i == (len(image_names) - 1):
- is_toggled = True
- if is_toggled:
- default_image_size = image_size
- self.toggled_image = image_name
-
- split_stuff = image_name.split('.')
- if "rootfs" in split_stuff:
- image_type = image_name[(len(split_stuff[0]) + len(".rootfs") + 1):]
- else:
- image_type = image_name[(len(split_stuff[0]) + 1):]
-
- self.image_store.append({'name': image_name,
- 'type': image_type,
- 'size': image_size,
- 'is_toggled': is_toggled,
- 'action_attr': image_attr,})
-
- i = i + 1
- self.num_toggled += is_toggled
-
- is_runnable = self.create_bottom_buttons(self.buttonlist, self.toggled_image)
-
- # Generated image files info
- varlist = ["Name: ", "Files created: ", "Directory: "]
- vallist = []
-
- vallist.append(image_name.split('.')[0])
- vallist.append(', '.join(fileitem['type'] for fileitem in self.image_store))
- vallist.append(image_addr)
-
- view_files_button = HobAltButton("View files")
- view_files_button.connect("clicked", self.view_files_clicked_cb, image_addr)
- view_files_button.set_tooltip_text("Open the directory containing the image files")
- open_log_button = None
- if log_file:
- open_log_button = HobAltButton("Open log")
- open_log_button.connect("clicked", self.open_log_clicked_cb, log_file)
- open_log_button.set_tooltip_text("Open the build's log file")
- self.image_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=view_files_button, button2=open_log_button)
- self.box_group_area.pack_start(self.image_detail, expand=False, fill=True)
-
- # The default kernel box for the qemu images
- self.sel_kernel = ""
- self.kernel_detail = None
- if 'qemu' in image_name:
- self.sel_kernel = self.get_kernel_file_name()
-
- # varlist = ["Kernel: "]
- # vallist = []
- # vallist.append(self.sel_kernel)
-
- # change_kernel_button = HobAltButton("Change")
- # change_kernel_button.connect("clicked", self.change_kernel_cb)
- # change_kernel_button.set_tooltip_text("Change qemu kernel file")
- # self.kernel_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=change_kernel_button)
- # self.box_group_area.pack_start(self.kernel_detail, expand=True, fill=True)
-
- # Machine, Image recipe and Layers
- layer_num_limit = 15
- varlist = ["Machine: ", "Image recipe: ", "Layers: "]
- vallist = []
- self.setting_detail = None
- if self.build_succeeded:
- vallist.append(machine)
- if self.builder.recipe_model.is_custom_image():
- if self.builder.configuration.initial_selected_image == self.builder.recipe_model.__custom_image__:
- base_image ="New image recipe"
- else:
- base_image = self.builder.configuration.initial_selected_image + " (edited)"
- vallist.append(base_image)
- i = 0
- for layer in layers:
- if i > layer_num_limit:
- break
- varlist.append(" - ")
- i += 1
- vallist.append("")
- i = 0
- for layer in layers:
- if i > layer_num_limit:
- break
- elif i == layer_num_limit:
- vallist.append("and more...")
- else:
- vallist.append(layer)
- i += 1
-
- edit_config_button = HobAltButton("Edit configuration")
- edit_config_button.set_tooltip_text("Edit machine and image recipe")
- edit_config_button.connect("clicked", self.edit_config_button_clicked_cb)
- self.setting_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=edit_config_button)
- self.box_group_area.pack_start(self.setting_detail, expand=True, fill=True)
-
- # Packages included, and Total image size
- varlist = ["Packages included: ", "Total image size: "]
- vallist = []
- vallist.append(pkg_num)
- vallist.append(default_image_size)
- self.builder.configuration.image_size = default_image_size
- self.builder.configuration.image_packages = self.builder.configuration.selected_packages
- if self.build_succeeded:
- edit_packages_button = HobAltButton("Edit packages")
- edit_packages_button.set_tooltip_text("Edit the packages included in your image")
- edit_packages_button.connect("clicked", self.edit_packages_button_clicked_cb)
- else: # get to this page from "My images"
- edit_packages_button = None
- self.package_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=edit_packages_button)
- self.box_group_area.pack_start(self.package_detail, expand=True, fill=True)
-
- # pack the buttons at the bottom, at this time they are already created.
- if self.build_succeeded:
- self.box_group_area.pack_end(self.details_bottom_buttons, expand=False, fill=False)
- else: # for "My images" page
- self.details_separator = gtk.HSeparator()
- self.box_group_area.pack_start(self.details_separator, expand=False, fill=False)
- self.box_group_area.pack_start(self.details_bottom_buttons, expand=False, fill=False)
-
- self.show_all()
- if self.kernel_detail and (not is_runnable):
- self.kernel_detail.hide()
- self.image_saved = False
-
- def view_files_clicked_cb(self, button, image_addr):
- subprocess.call("xdg-open /%s" % image_addr, shell=True)
-
- def open_log_clicked_cb(self, button, log_file):
- if log_file:
- log_file = "file:///" + log_file
- gtk.show_uri(screen=button.get_screen(), uri=log_file, timestamp=0)
-
- def refresh_package_detail_box(self, image_size):
- self.package_detail.update_line_widgets("Total image size: ", image_size)
-
- def test_type_runnable(self, image_name):
- type_runnable = False
- for t in self.builder.parameters.runnable_image_types:
- if image_name.endswith(t):
- type_runnable = True
- break
- return type_runnable
-
- def test_mach_runnable(self, image_name):
- mach_runnable = False
- for t in self.builder.parameters.runnable_machine_patterns:
- if t in image_name:
- mach_runnable = True
- break
- return mach_runnable
-
- def test_deployable(self, image_name):
- if self.builder.configuration.curr_mach.startswith("qemu"):
- return False
- deployable = False
- for t in self.builder.parameters.deployable_image_types:
- if image_name.endswith(t):
- deployable = True
- break
- return deployable
-
- def get_kernel_file_name(self, kernel_addr=""):
- kernel_name = ""
-
- if not kernel_addr:
- kernel_addr = self.builder.parameters.image_addr
-
- files = [f for f in os.listdir(kernel_addr) if f[0] <> '.']
- for check_file in files:
- if check_file.endswith(".bin"):
- name_splits = check_file.split(".")[0]
- if self.builder.parameters.kernel_image_type in name_splits.split("-"):
- kernel_name = check_file
- break
-
- return kernel_name
-
- def show_builded_images_dialog(self, widget, primary_action=""):
- title = primary_action if primary_action else "Your builded images"
- dialog = CrumbsDialog(title, self.builder,
- gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
- dialog.set_border_width(12)
-
- label = gtk.Label()
- label.set_use_markup(True)
- label.set_alignment(0.0, 0.5)
- label.set_padding(12,0)
- if primary_action == "Run image":
- label.set_markup("<span font_desc='12'>Select the image file you want to run:</span>")
- elif primary_action == "Deploy image":
- label.set_markup("<span font_desc='12'>Select the image file you want to deploy:</span>")
- else:
- label.set_markup("<span font_desc='12'>Select the image file you want to %s</span>" % primary_action)
- dialog.vbox.pack_start(label, expand=False, fill=False)
-
- # filter created images as action attribution (deploy or run)
- action_attr = ""
- action_images = []
- for fileitem in self.image_store:
- action_attr = fileitem['action_attr']
- if (action_attr == 'run' and primary_action == "Run image") \
- or (action_attr == 'deploy' and primary_action == "Deploy image"):
- action_images.append(fileitem)
-
- # pack the corresponding 'runnable' or 'deploy' radio_buttons, if there has no more than one file.
- # assume that there does not both have 'deploy' and 'runnable' files in the same building result
- # in possible as design.
- curr_row = 0
- rows = (len(action_images)) if len(action_images) < 10 else 10
- table = gtk.Table(rows, 10, True)
- table.set_row_spacings(6)
- table.set_col_spacing(0, 12)
- table.set_col_spacing(5, 12)
-
- sel_parent_btn = None
- for fileitem in action_images:
- sel_btn = gtk.RadioButton(sel_parent_btn, fileitem['type'])
- sel_parent_btn = sel_btn if not sel_parent_btn else sel_parent_btn
- sel_btn.set_active(fileitem['is_toggled'])
- sel_btn.connect('toggled', self.table_selected_cb, fileitem)
- if curr_row < 10:
- table.attach(sel_btn, 0, 4, curr_row, curr_row + 1, xpadding=24)
- else:
- table.attach(sel_btn, 5, 9, curr_row - 10, curr_row - 9, xpadding=24)
- curr_row += 1
-
- dialog.vbox.pack_start(table, expand=False, fill=False, padding=6)
-
- button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL)
- HobAltButton.style_button(button)
-
- if primary_action:
- button = dialog.add_button(primary_action, gtk.RESPONSE_YES)
- HobButton.style_button(button)
-
- dialog.show_all()
-
- response = dialog.run()
- dialog.destroy()
-
- if response != gtk.RESPONSE_YES:
- return
-
- for fileitem in self.image_store:
- if fileitem['is_toggled']:
- if fileitem['action_attr'] == 'run':
- self.builder.runqemu_image(fileitem['name'], self.sel_kernel)
- elif fileitem['action_attr'] == 'deploy':
- self.builder.deploy_image(fileitem['name'])
-
- def table_selected_cb(self, tbutton, image):
- image['is_toggled'] = tbutton.get_active()
- if image['is_toggled']:
- self.toggled_image = image['name']
-
- def change_kernel_cb(self, widget):
- kernel_path = self.builder.show_load_kernel_dialog()
- if kernel_path and self.kernel_detail:
- import os.path
- self.sel_kernel = os.path.basename(kernel_path)
- markup = self.kernel_detail.format_line("Kernel: ", self.sel_kernel)
- label = ((self.kernel_detail.get_children()[0]).get_children()[0]).get_children()[0]
- label.set_markup(markup)
-
- def create_bottom_buttons(self, buttonlist, image_name):
- # Create the buttons at the bottom
- created = False
- packed = False
- self.button_ids = {}
- is_runnable = False
-
- # create button "Deploy image"
- name = "Deploy image"
- if name in buttonlist and self.test_deployable(image_name):
- deploy_button = HobButton('Deploy image')
- #deploy_button.set_size_request(205, 49)
- deploy_button.set_tooltip_text("Burn a live image to a USB drive or flash memory")
- deploy_button.set_flags(gtk.CAN_DEFAULT)
- button_id = deploy_button.connect("clicked", self.deploy_button_clicked_cb)
- self.button_ids[button_id] = deploy_button
- self.details_bottom_buttons.pack_end(deploy_button, expand=False, fill=False)
- created = True
- packed = True
-
- name = "Run image"
- if name in buttonlist and self.test_type_runnable(image_name) and self.test_mach_runnable(image_name):
- if created == True:
- # separator
- #label = gtk.Label(" or ")
- #self.details_bottom_buttons.pack_end(label, expand=False, fill=False)
-
- # create button "Run image"
- run_button = HobAltButton("Run image")
- else:
- # create button "Run image" as the primary button
- run_button = HobButton("Run image")
- #run_button.set_size_request(205, 49)
- run_button.set_flags(gtk.CAN_DEFAULT)
- packed = True
- run_button.set_tooltip_text("Start up an image with qemu emulator")
- button_id = run_button.connect("clicked", self.run_button_clicked_cb)
- self.button_ids[button_id] = run_button
- self.details_bottom_buttons.pack_end(run_button, expand=False, fill=False)
- created = True
- is_runnable = True
-
- name = "Save image recipe"
- if name in buttonlist and self.builder.recipe_model.is_custom_image():
- save_button = HobAltButton("Save image recipe")
- save_button.set_tooltip_text("Keep your changes saving them as an image recipe")
- save_button.set_sensitive(not self.image_saved)
- button_id = save_button.connect("clicked", self.save_button_clicked_cb)
- self.button_ids[button_id] = save_button
- self.details_bottom_buttons.pack_end(save_button, expand=False, fill=False)
-
- name = "Build new image"
- if name in buttonlist:
- # create button "Build new image"
- if packed:
- build_new_button = HobAltButton("Build new image")
- else:
- build_new_button = HobButton("Build new image")
- build_new_button.set_flags(gtk.CAN_DEFAULT)
- #build_new_button.set_size_request(205, 49)
- self.details_bottom_buttons.pack_end(build_new_button, expand=False, fill=False)
- build_new_button.set_tooltip_text("Create a new image from scratch")
- button_id = build_new_button.connect("clicked", self.build_new_button_clicked_cb)
- self.button_ids[button_id] = build_new_button
-
- return is_runnable
-
- def deploy_button_clicked_cb(self, button):
- if self.toggled_image:
- if self.num_toggled > 1:
- self.set_sensitive(False)
- self.show_builded_images_dialog(None, "Deploy image")
- self.set_sensitive(True)
- else:
- self.builder.deploy_image(self.toggled_image)
-
- def run_button_clicked_cb(self, button):
- if self.toggled_image:
- if self.num_toggled > 1:
- self.set_sensitive(False)
- self.show_builded_images_dialog(None, "Run image")
- self.set_sensitive(True)
- else:
- self.builder.runqemu_image(self.toggled_image, self.sel_kernel)
-
- def save_button_clicked_cb(self, button):
- topdir = self.builder.get_topdir()
- images_dir = topdir + "/recipes/images/custom/"
- self.builder.ensure_dir(images_dir)
-
- self.name_field_template = self.builder.image_configuration_page.custom_image_selected
- if self.name_field_template:
- image_path = self.builder.recipe_model.pn_path[self.name_field_template]
- image_iter = self.builder.recipe_model.get_iter(image_path)
- self.description_field_template = self.builder.recipe_model.get_value(image_iter, self.builder.recipe_model.COL_DESC)
- else:
- self.name_field_template = ""
-
- dialog = SaveImageDialog(images_dir, self.name_field_template, self.description_field_template,
- "Save image recipe", self.builder, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
- response = dialog.run()
- dialog.destroy()
-
- def build_new_button_clicked_cb(self, button):
- self.builder.initiate_new_build_async()
-
- def edit_config_button_clicked_cb(self, button):
- self.builder.show_configuration()
-
- def edit_packages_button_clicked_cb(self, button):
- self.builder.show_packages()
-
- def my_images_button_clicked_cb(self, button):
- self.builder.show_load_my_images_dialog()
-
- def settings_button_clicked_cb(self, button):
- # Create an advanced settings dialog
- response, settings_changed = self.builder.show_simple_settings_dialog()
- if not response:
- return
- if settings_changed:
- self.builder.reparse_post_adv_settings()
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/packageselectionpage.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/packageselectionpage.py
deleted file mode 100755
index 7c62b36e6..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/packageselectionpage.py
+++ /dev/null
@@ -1,355 +0,0 @@
-#!/usr/bin/env python
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2012 Intel Corporation
-#
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import gtk
-import glib
-from bb.ui.crumbs.hobcolor import HobColors
-from bb.ui.crumbs.hobwidget import HobViewTable, HobNotebook, HobAltButton, HobButton
-from bb.ui.crumbs.hoblistmodel import PackageListModel
-from bb.ui.crumbs.hobpages import HobPage
-
-#
-# PackageSelectionPage
-#
-class PackageSelectionPage (HobPage):
-
- pages = [
- {
- 'name' : 'Included packages',
- 'tooltip' : 'The packages currently included for your image',
- 'filter' : { PackageListModel.COL_INC : [True] },
- 'search' : 'Search packages by name',
- 'searchtip' : 'Enter a package name to find it',
- 'columns' : [{
- 'col_name' : 'Package name',
- 'col_id' : PackageListModel.COL_NAME,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 300,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Size',
- 'col_id' : PackageListModel.COL_SIZE,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 300,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Recipe',
- 'col_id' : PackageListModel.COL_RCP,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 250,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Brought in by (+others)',
- 'col_id' : PackageListModel.COL_BINB,
- 'col_style': 'binb',
- 'col_min' : 100,
- 'col_max' : 350,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Included',
- 'col_id' : PackageListModel.COL_INC,
- 'col_style': 'check toggle',
- 'col_min' : 100,
- 'col_max' : 100
- }]
- }, {
- 'name' : 'All packages',
- 'tooltip' : 'All packages that have been built',
- 'filter' : {},
- 'search' : 'Search packages by name',
- 'searchtip' : 'Enter a package name to find it',
- 'columns' : [{
- 'col_name' : 'Package name',
- 'col_id' : PackageListModel.COL_NAME,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 400,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Size',
- 'col_id' : PackageListModel.COL_SIZE,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 500,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Recipe',
- 'col_id' : PackageListModel.COL_RCP,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 250,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Included',
- 'col_id' : PackageListModel.COL_INC,
- 'col_style': 'check toggle',
- 'col_min' : 100,
- 'col_max' : 100
- }]
- }
- ]
-
- (INCLUDED,
- ALL) = range(2)
-
- def __init__(self, builder):
- super(PackageSelectionPage, self).__init__(builder, "Edit packages")
-
- # set invisible members
- self.recipe_model = self.builder.recipe_model
- self.package_model = self.builder.package_model
-
- # create visual elements
- self.create_visual_elements()
-
- def included_clicked_cb(self, button):
- self.ins.set_current_page(self.INCLUDED)
-
- def create_visual_elements(self):
- self.label = gtk.Label("Packages included: 0\nSelected packages size: 0 MB")
- self.eventbox = self.add_onto_top_bar(self.label, 73)
- self.pack_start(self.eventbox, expand=False, fill=False)
- self.pack_start(self.group_align, expand=True, fill=True)
-
- # set visible members
- self.ins = HobNotebook()
- self.tables = [] # we need to modify table when the dialog is shown
-
- search_names = []
- search_tips = []
- # append the tab
- for page in self.pages:
- columns = page['columns']
- name = page['name']
- tab = HobViewTable(columns, name)
- search_names.append(page['search'])
- search_tips.append(page['searchtip'])
- filter = page['filter']
- sort_model = self.package_model.tree_model(filter, initial=True)
- tab.set_model(sort_model)
- tab.connect("toggled", self.table_toggled_cb, name)
- tab.connect("button-release-event", self.button_click_cb)
- tab.connect("cell-fadeinout-stopped", self.after_fadeout_checkin_include, filter)
- self.ins.append_page(tab, page['name'], page['tooltip'])
- self.tables.append(tab)
-
- self.ins.set_entry(search_names, search_tips)
- self.ins.search.connect("changed", self.search_entry_changed)
-
- # add all into the dialog
- self.box_group_area.pack_start(self.ins, expand=True, fill=True)
-
- self.button_box = gtk.HBox(False, 6)
- self.box_group_area.pack_start(self.button_box, expand=False, fill=False)
-
- self.build_image_button = HobButton('Build image')
- #self.build_image_button.set_size_request(205, 49)
- self.build_image_button.set_tooltip_text("Build target image")
- self.build_image_button.set_flags(gtk.CAN_DEFAULT)
- self.build_image_button.grab_default()
- self.build_image_button.connect("clicked", self.build_image_clicked_cb)
- self.button_box.pack_end(self.build_image_button, expand=False, fill=False)
-
- self.back_button = HobAltButton('Cancel')
- self.back_button.connect("clicked", self.back_button_clicked_cb)
- self.button_box.pack_end(self.back_button, expand=False, fill=False)
-
- def search_entry_changed(self, entry):
- text = entry.get_text()
- if self.ins.search_focus:
- self.ins.search_focus = False
- elif self.ins.page_changed:
- self.ins.page_change = False
- self.filter_search(entry)
- elif text not in self.ins.search_names:
- self.filter_search(entry)
-
- def filter_search(self, entry):
- text = entry.get_text()
- current_tab = self.ins.get_current_page()
- filter = self.pages[current_tab]['filter']
- filter[PackageListModel.COL_NAME] = text
- self.tables[current_tab].set_model(self.package_model.tree_model(filter, search_data=text))
- if self.package_model.filtered_nb == 0:
- if not self.ins.get_nth_page(current_tab).top_bar:
- self.ins.get_nth_page(current_tab).add_no_result_bar(entry)
- self.ins.get_nth_page(current_tab).top_bar.set_no_show_all(True)
- self.ins.get_nth_page(current_tab).top_bar.show()
- self.ins.get_nth_page(current_tab).scroll.hide()
- else:
- if self.ins.get_nth_page(current_tab).top_bar:
- self.ins.get_nth_page(current_tab).top_bar.hide()
- self.ins.get_nth_page(current_tab).scroll.show()
- if entry.get_text() == '':
- entry.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, False)
- else:
- entry.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, True)
-
- def button_click_cb(self, widget, event):
- path, col = widget.table_tree.get_cursor()
- tree_model = widget.table_tree.get_model()
- if path and col.get_title() != 'Included': # else activation is likely a removal
- properties = {'binb': '' , 'name': '', 'size':'', 'recipe':'', 'files_list':''}
- properties['binb'] = tree_model.get_value(tree_model.get_iter(path), PackageListModel.COL_BINB)
- properties['name'] = tree_model.get_value(tree_model.get_iter(path), PackageListModel.COL_NAME)
- properties['size'] = tree_model.get_value(tree_model.get_iter(path), PackageListModel.COL_SIZE)
- properties['recipe'] = tree_model.get_value(tree_model.get_iter(path), PackageListModel.COL_RCP)
- properties['files_list'] = tree_model.get_value(tree_model.get_iter(path), PackageListModel.COL_FLIST)
-
- self.builder.show_recipe_property_dialog(properties)
-
- def open_log_clicked_cb(self, button, log_file):
- if log_file:
- log_file = "file:///" + log_file
- gtk.show_uri(screen=button.get_screen(), uri=log_file, timestamp=0)
-
- def show_page(self, log_file):
- children = self.button_box.get_children() or []
- for child in children:
- self.button_box.remove(child)
- # re-packed the buttons as request, add the 'open log' button if build success
- self.button_box.pack_end(self.build_image_button, expand=False, fill=False)
- if log_file:
- open_log_button = HobAltButton("Open log")
- open_log_button.connect("clicked", self.open_log_clicked_cb, log_file)
- open_log_button.set_tooltip_text("Open the build's log file")
- self.button_box.pack_end(open_log_button, expand=False, fill=False)
- self.button_box.pack_end(self.back_button, expand=False, fill=False)
- self.show_all()
-
- def build_image_clicked_cb(self, button):
- self.builder.parsing_warnings = []
- self.builder.build_image()
-
- def refresh_tables(self):
- self.ins.reset_entry(self.ins.search, 0)
- for tab in self.tables:
- index = self.tables.index(tab)
- filter = self.pages[index]['filter']
- tab.set_model(self.package_model.tree_model(filter, initial=True))
-
- def back_button_clicked_cb(self, button):
- if self.builder.previous_step == self.builder.IMAGE_GENERATED:
- self.builder.restore_initial_selected_packages()
- self.refresh_selection()
- self.builder.show_image_details()
- else:
- self.builder.show_configuration()
- self.refresh_tables()
-
- def refresh_selection(self):
- self.builder.configuration.selected_packages = self.package_model.get_selected_packages()
- self.builder.configuration.user_selected_packages = self.package_model.get_user_selected_packages()
- selected_packages_num = len(self.builder.configuration.selected_packages)
- selected_packages_size = self.package_model.get_packages_size()
- selected_packages_size_str = HobPage._size_to_string(selected_packages_size)
-
- if self.builder.configuration.image_packages == self.builder.configuration.selected_packages:
- image_total_size_str = self.builder.configuration.image_size
- else:
- image_overhead_factor = self.builder.configuration.image_overhead_factor
- image_rootfs_size = self.builder.configuration.image_rootfs_size / 1024 # image_rootfs_size is KB
- image_extra_size = self.builder.configuration.image_extra_size / 1024 # image_extra_size is KB
- base_size = image_overhead_factor * selected_packages_size
- image_total_size = max(base_size, image_rootfs_size) + image_extra_size
- if "zypper" in self.builder.configuration.selected_packages:
- image_total_size += (51200 * 1024)
- image_total_size_str = HobPage._size_to_string(image_total_size)
-
- self.label.set_label("Packages included: %s\nSelected packages size: %s\nEstimated image size: %s" %
- (selected_packages_num, selected_packages_size_str, image_total_size_str))
- self.ins.show_indicator_icon("Included packages", selected_packages_num)
-
- def toggle_item_idle_cb(self, path, view_tree, cell, pagename):
- if not self.package_model.path_included(path):
- self.package_model.include_item(item_path=path, binb="User Selected")
- else:
- self.pre_fadeout_checkout_include(view_tree)
- self.package_model.exclude_item(item_path=path)
- self.render_fadeout(view_tree, cell)
-
- self.refresh_selection()
- if not self.builder.customized:
- self.builder.customized = True
- self.builder.set_base_image()
- self.builder.configuration.selected_image = self.recipe_model.__custom_image__
- self.builder.rcppkglist_populated()
-
- self.builder.window_sensitive(True)
- view_model = view_tree.get_model()
- vpath = self.package_model.convert_path_to_vpath(view_model, path)
- view_tree.set_cursor(vpath)
-
- def table_toggled_cb(self, table, cell, view_path, toggled_columnid, view_tree, pagename):
- # Click to include a package
- self.builder.window_sensitive(False)
- view_model = view_tree.get_model()
- path = self.package_model.convert_vpath_to_path(view_model, view_path)
- glib.idle_add(self.toggle_item_idle_cb, path, view_tree, cell, pagename)
-
- def pre_fadeout_checkout_include(self, tree):
- #after the fadeout the table will be sorted as before
- self.sort_column_id = self.package_model.sort_column_id
- self.sort_order = self.package_model.sort_order
-
- self.package_model.resync_fadeout_column(self.package_model.get_iter_first())
- # Check out a model which base on the column COL_FADE_INC,
- # it's save the prev state of column COL_INC before do exclude_item
- filter = { PackageListModel.COL_FADE_INC : [True]}
- new_model = self.package_model.tree_model(filter, excluded_items_ahead=True)
- tree.set_model(new_model)
- tree.expand_all()
-
- def get_excluded_rows(self, to_render_cells, model, it):
- while it:
- path = model.get_path(it)
- prev_cell_is_active = model.get_value(it, PackageListModel.COL_FADE_INC)
- curr_cell_is_active = model.get_value(it, PackageListModel.COL_INC)
- if (prev_cell_is_active == True) and (curr_cell_is_active == False):
- to_render_cells.append(path)
- if model.iter_has_child(it):
- self.get_excluded_rows(to_render_cells, model, model.iter_children(it))
- it = model.iter_next(it)
-
- return to_render_cells
-
- def render_fadeout(self, tree, cell):
- if (not cell) or (not tree):
- return
- to_render_cells = []
- view_model = tree.get_model()
- self.get_excluded_rows(to_render_cells, view_model, view_model.get_iter_first())
-
- cell.fadeout(tree, 1000, to_render_cells)
-
- def after_fadeout_checkin_include(self, table, ctrl, cell, tree, filter):
- self.package_model.sort_column_id = self.sort_column_id
- self.package_model.sort_order = self.sort_order
- tree.set_model(self.package_model.tree_model(filter))
- tree.expand_all()
-
- def set_packages_curr_tab(self, curr_page):
- self.ins.set_current_page(curr_page)
-
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/recipeselectionpage.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/recipeselectionpage.py
deleted file mode 100755
index 58db43f70..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/recipeselectionpage.py
+++ /dev/null
@@ -1,335 +0,0 @@
-#!/usr/bin/env python
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2012 Intel Corporation
-#
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import gtk
-import glib
-from bb.ui.crumbs.hobcolor import HobColors
-from bb.ui.crumbs.hobwidget import HobViewTable, HobNotebook, HobAltButton, HobButton
-from bb.ui.crumbs.hoblistmodel import RecipeListModel
-from bb.ui.crumbs.hobpages import HobPage
-
-#
-# RecipeSelectionPage
-#
-class RecipeSelectionPage (HobPage):
- pages = [
- {
- 'name' : 'Included recipes',
- 'tooltip' : 'The recipes currently included for your image',
- 'filter' : { RecipeListModel.COL_INC : [True],
- RecipeListModel.COL_TYPE : ['recipe', 'packagegroup'] },
- 'search' : 'Search recipes by name',
- 'searchtip' : 'Enter a recipe name to find it',
- 'columns' : [{
- 'col_name' : 'Recipe name',
- 'col_id' : RecipeListModel.COL_NAME,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 400,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Group',
- 'col_id' : RecipeListModel.COL_GROUP,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 300,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Brought in by (+others)',
- 'col_id' : RecipeListModel.COL_BINB,
- 'col_style': 'binb',
- 'col_min' : 100,
- 'col_max' : 500,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Included',
- 'col_id' : RecipeListModel.COL_INC,
- 'col_style': 'check toggle',
- 'col_min' : 100,
- 'col_max' : 100
- }]
- }, {
- 'name' : 'All recipes',
- 'tooltip' : 'All recipes in your configured layers',
- 'filter' : { RecipeListModel.COL_TYPE : ['recipe'] },
- 'search' : 'Search recipes by name',
- 'searchtip' : 'Enter a recipe name to find it',
- 'columns' : [{
- 'col_name' : 'Recipe name',
- 'col_id' : RecipeListModel.COL_NAME,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 400,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Group',
- 'col_id' : RecipeListModel.COL_GROUP,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 400,
- 'expand' : 'True'
- }, {
- 'col_name' : 'License',
- 'col_id' : RecipeListModel.COL_LIC,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 400,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Included',
- 'col_id' : RecipeListModel.COL_INC,
- 'col_style': 'check toggle',
- 'col_min' : 100,
- 'col_max' : 100
- }]
- }, {
- 'name' : 'Package Groups',
- 'tooltip' : 'All package groups in your configured layers',
- 'filter' : { RecipeListModel.COL_TYPE : ['packagegroup'] },
- 'search' : 'Search package groups by name',
- 'searchtip' : 'Enter a package group name to find it',
- 'columns' : [{
- 'col_name' : 'Package group name',
- 'col_id' : RecipeListModel.COL_NAME,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 400,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Included',
- 'col_id' : RecipeListModel.COL_INC,
- 'col_style': 'check toggle',
- 'col_min' : 100,
- 'col_max' : 100
- }]
- }
- ]
-
- (INCLUDED,
- ALL,
- TASKS) = range(3)
-
- def __init__(self, builder = None):
- super(RecipeSelectionPage, self).__init__(builder, "Step 1 of 2: Edit recipes")
-
- # set invisible members
- self.recipe_model = self.builder.recipe_model
-
- # create visual elements
- self.create_visual_elements()
-
- def included_clicked_cb(self, button):
- self.ins.set_current_page(self.INCLUDED)
-
- def create_visual_elements(self):
- self.eventbox = self.add_onto_top_bar(None, 73)
- self.pack_start(self.eventbox, expand=False, fill=False)
- self.pack_start(self.group_align, expand=True, fill=True)
-
- # set visible members
- self.ins = HobNotebook()
- self.tables = [] # we need modify table when the dialog is shown
-
- search_names = []
- search_tips = []
- # append the tabs in order
- for page in self.pages:
- columns = page['columns']
- name = page['name']
- tab = HobViewTable(columns, name)
- search_names.append(page['search'])
- search_tips.append(page['searchtip'])
- filter = page['filter']
- sort_model = self.recipe_model.tree_model(filter, initial=True)
- tab.set_model(sort_model)
- tab.connect("toggled", self.table_toggled_cb, name)
- tab.connect("button-release-event", self.button_click_cb)
- tab.connect("cell-fadeinout-stopped", self.after_fadeout_checkin_include, filter)
- self.ins.append_page(tab, page['name'], page['tooltip'])
- self.tables.append(tab)
-
- self.ins.set_entry(search_names, search_tips)
- self.ins.search.connect("changed", self.search_entry_changed)
-
- # add all into the window
- self.box_group_area.pack_start(self.ins, expand=True, fill=True)
-
- button_box = gtk.HBox(False, 6)
- self.box_group_area.pack_end(button_box, expand=False, fill=False)
-
- self.build_packages_button = HobButton('Build packages')
- #self.build_packages_button.set_size_request(205, 49)
- self.build_packages_button.set_tooltip_text("Build selected recipes into packages")
- self.build_packages_button.set_flags(gtk.CAN_DEFAULT)
- self.build_packages_button.grab_default()
- self.build_packages_button.connect("clicked", self.build_packages_clicked_cb)
- button_box.pack_end(self.build_packages_button, expand=False, fill=False)
-
- self.back_button = HobAltButton('Cancel')
- self.back_button.connect("clicked", self.back_button_clicked_cb)
- button_box.pack_end(self.back_button, expand=False, fill=False)
-
- def search_entry_changed(self, entry):
- text = entry.get_text()
- if self.ins.search_focus:
- self.ins.search_focus = False
- elif self.ins.page_changed:
- self.ins.page_change = False
- self.filter_search(entry)
- elif text not in self.ins.search_names:
- self.filter_search(entry)
-
- def filter_search(self, entry):
- text = entry.get_text()
- current_tab = self.ins.get_current_page()
- filter = self.pages[current_tab]['filter']
- filter[RecipeListModel.COL_NAME] = text
- self.tables[current_tab].set_model(self.recipe_model.tree_model(filter, search_data=text))
- if self.recipe_model.filtered_nb == 0:
- if not self.ins.get_nth_page(current_tab).top_bar:
- self.ins.get_nth_page(current_tab).add_no_result_bar(entry)
- self.ins.get_nth_page(current_tab).top_bar.set_no_show_all(True)
- self.ins.get_nth_page(current_tab).top_bar.show()
- self.ins.get_nth_page(current_tab).scroll.hide()
- else:
- if self.ins.get_nth_page(current_tab).top_bar:
- self.ins.get_nth_page(current_tab).top_bar.hide()
- self.ins.get_nth_page(current_tab).scroll.show()
- if entry.get_text() == '':
- entry.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, False)
- else:
- entry.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, True)
-
- def button_click_cb(self, widget, event):
- path, col = widget.table_tree.get_cursor()
- tree_model = widget.table_tree.get_model()
- if path and col.get_title() != 'Included': # else activation is likely a removal
- properties = {'summary': '', 'name': '', 'version': '', 'revision': '', 'binb': '', 'group': '', 'license': '', 'homepage': '', 'bugtracker': '', 'description': ''}
- properties['summary'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_SUMMARY)
- properties['name'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_NAME)
- properties['version'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_VERSION)
- properties['revision'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_REVISION)
- properties['binb'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_BINB)
- properties['group'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_GROUP)
- properties['license'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_LIC)
- properties['homepage'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_HOMEPAGE)
- properties['bugtracker'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_BUGTRACKER)
- properties['description'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_DESC)
- self.builder.show_recipe_property_dialog(properties)
-
- def build_packages_clicked_cb(self, button):
- self.refresh_tables()
- self.builder.build_packages()
-
- def refresh_tables(self):
- self.ins.reset_entry(self.ins.search, 0)
- for tab in self.tables:
- index = self.tables.index(tab)
- filter = self.pages[index]['filter']
- tab.set_model(self.recipe_model.tree_model(filter, search_data="", initial=True))
-
- def back_button_clicked_cb(self, button):
- self.builder.recipe_model.set_selected_image(self.builder.configuration.initial_selected_image)
- self.builder.image_configuration_page.update_image_combo(self.builder.recipe_model, self.builder.configuration.initial_selected_image)
- self.builder.image_configuration_page.update_image_desc()
- self.builder.show_configuration()
- self.refresh_tables()
-
- def refresh_selection(self):
- self.builder.configuration.selected_image = self.recipe_model.get_selected_image()
- _, self.builder.configuration.selected_recipes = self.recipe_model.get_selected_recipes()
- self.ins.show_indicator_icon("Included recipes", len(self.builder.configuration.selected_recipes))
-
- def toggle_item_idle_cb(self, path, view_tree, cell, pagename):
- if not self.recipe_model.path_included(path):
- self.recipe_model.include_item(item_path=path, binb="User Selected", image_contents=False)
- else:
- self.pre_fadeout_checkout_include(view_tree, pagename)
- self.recipe_model.exclude_item(item_path=path)
- self.render_fadeout(view_tree, cell)
-
- self.refresh_selection()
- if not self.builder.customized:
- self.builder.customized = True
- self.builder.configuration.selected_image = self.recipe_model.__custom_image__
- self.builder.rcppkglist_populated()
-
- self.builder.window_sensitive(True)
-
- view_model = view_tree.get_model()
- vpath = self.recipe_model.convert_path_to_vpath(view_model, path)
- view_tree.set_cursor(vpath)
-
- def table_toggled_cb(self, table, cell, view_path, toggled_columnid, view_tree, pagename):
- # Click to include a recipe
- self.builder.window_sensitive(False)
- view_model = view_tree.get_model()
- path = self.recipe_model.convert_vpath_to_path(view_model, view_path)
- glib.idle_add(self.toggle_item_idle_cb, path, view_tree, cell, pagename)
-
- def pre_fadeout_checkout_include(self, tree, pagename):
- #after the fadeout the table will be sorted as before
- self.sort_column_id = self.recipe_model.sort_column_id
- self.sort_order = self.recipe_model.sort_order
-
- #resync the included items to a backup fade include column
- it = self.recipe_model.get_iter_first()
- while it:
- active = self.recipe_model.get_value(it, self.recipe_model.COL_INC)
- self.recipe_model.set(it, self.recipe_model.COL_FADE_INC, active)
- it = self.recipe_model.iter_next(it)
- # Check out a model which base on the column COL_FADE_INC,
- # it's save the prev state of column COL_INC before do exclude_item
- filter = { RecipeListModel.COL_FADE_INC:[True] }
- if pagename == "Included recipes":
- filter[RecipeListModel.COL_TYPE] = ['recipe', 'packagegroup']
- elif pagename == "All recipes":
- filter[RecipeListModel.COL_TYPE] = ['recipe']
- else:
- filter[RecipeListModel.COL_TYPE] = ['packagegroup']
-
- new_model = self.recipe_model.tree_model(filter, excluded_items_ahead=True)
- tree.set_model(new_model)
-
- def render_fadeout(self, tree, cell):
- if (not cell) or (not tree):
- return
- to_render_cells = []
- model = tree.get_model()
- it = model.get_iter_first()
- while it:
- path = model.get_path(it)
- prev_cell_is_active = model.get_value(it, RecipeListModel.COL_FADE_INC)
- curr_cell_is_active = model.get_value(it, RecipeListModel.COL_INC)
- if (prev_cell_is_active == True) and (curr_cell_is_active == False):
- to_render_cells.append(path)
- it = model.iter_next(it)
-
- cell.fadeout(tree, 1000, to_render_cells)
-
- def after_fadeout_checkin_include(self, table, ctrl, cell, tree, filter):
- self.recipe_model.sort_column_id = self.sort_column_id
- self.recipe_model.sort_order = self.sort_order
- tree.set_model(self.recipe_model.tree_model(filter))
-
- def set_recipe_curr_tab(self, curr_page):
- self.ins.set_current_page(curr_page)
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/sanitycheckpage.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/sanitycheckpage.py
deleted file mode 100644
index 76ce2ecc2..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/sanitycheckpage.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env python
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2012 Intel Corporation
-#
-# Authored by Bogdan Marinescu <bogdan.a.marinescu@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import gtk, gobject
-from bb.ui.crumbs.progressbar import HobProgressBar
-from bb.ui.crumbs.hobwidget import hic
-from bb.ui.crumbs.hobpages import HobPage
-
-#
-# SanityCheckPage
-#
-class SanityCheckPage (HobPage):
-
- def __init__(self, builder):
- super(SanityCheckPage, self).__init__(builder)
- self.running = False
- self.create_visual_elements()
- self.show_all()
-
- def make_label(self, text, bold=True):
- label = gtk.Label()
- label.set_alignment(0.0, 0.5)
- mark = "<span %s>%s</span>" % (self.span_tag('x-large', 'bold') if bold else self.span_tag('medium'), text)
- label.set_markup(mark)
- return label
-
- def start(self):
- if not self.running:
- self.running = True
- gobject.timeout_add(100, self.timer_func)
-
- def stop(self):
- self.running = False
-
- def is_running(self):
- return self.running
-
- def timer_func(self):
- self.progress_bar.pulse()
- return self.running
-
- def create_visual_elements(self):
- # Table'd layout. 'rows' and 'cols' give the table size
- rows, cols = 30, 50
- self.table = gtk.Table(rows, cols, True)
- self.pack_start(self.table, expand=False, fill=False)
- sx, sy = 2, 2
- # 'info' icon
- image = gtk.Image()
- image.set_from_file(hic.ICON_INFO_DISPLAY_FILE)
- self.table.attach(image, sx, sx + 2, sy, sy + 3 )
- image.show()
- # 'Checking' message
- label = self.make_label('Hob is checking for correct build system setup')
- self.table.attach(label, sx + 2, cols, sy, sy + 3, xpadding=5 )
- label.show()
- # 'Shouldn't take long' message.
- label = self.make_label("The check shouldn't take long.", False)
- self.table.attach(label, sx + 2, cols, sy + 3, sy + 4, xpadding=5)
- label.show()
- # Progress bar
- self.progress_bar = HobProgressBar()
- self.table.attach(self.progress_bar, sx + 2, cols - 3, sy + 5, sy + 7, xpadding=5)
- self.progress_bar.show()
- # All done
- self.table.show()
-
diff --git a/yocto-poky/bitbake/lib/bb/ui/hob.py b/yocto-poky/bitbake/lib/bb/ui/hob.py
deleted file mode 100755
index da5b41189..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/hob.py
+++ /dev/null
@@ -1,109 +0,0 @@
-#!/usr/bin/env python
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2011 Intel Corporation
-#
-# Authored by Joshua Lock <josh@linux.intel.com>
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import sys
-import os
-requirements = "FATAL: Hob requires Gtk+ 2.20.0 or higher, PyGtk 2.21.0 or higher"
-try:
- import gobject
- import gtk
- import pygtk
- pygtk.require('2.0') # to be certain we don't have gtk+ 1.x !?!
- gtkver = gtk.gtk_version
- pygtkver = gtk.pygtk_version
- if gtkver < (2, 20, 0) or pygtkver < (2, 21, 0):
- sys.exit("%s,\nYou have Gtk+ %s and PyGtk %s." % (requirements,
- ".".join(map(str, gtkver)),
- ".".join(map(str, pygtkver))))
-except ImportError as exc:
- sys.exit("%s (%s)." % (requirements, str(exc)))
-sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
-try:
- import bb
-except RuntimeError as exc:
- sys.exit(str(exc))
-from bb.ui import uihelper
-from bb.ui.crumbs.hoblistmodel import RecipeListModel, PackageListModel
-from bb.ui.crumbs.hobeventhandler import HobHandler
-from bb.ui.crumbs.builder import Builder
-
-featureSet = [bb.cooker.CookerFeatures.HOB_EXTRA_CACHES, bb.cooker.CookerFeatures.BASEDATASTORE_TRACKING]
-
-def event_handle_idle_func(eventHandler, hobHandler):
- # Consume as many messages as we can in the time available to us
- if not eventHandler:
- return False
- event = eventHandler.getEvent()
- while event:
- hobHandler.handle_event(event)
- event = eventHandler.getEvent()
- return True
-
-_evt_list = [ "bb.runqueue.runQueueExitWait", "bb.event.LogExecTTY", "logging.LogRecord",
- "bb.build.TaskFailed", "bb.build.TaskBase", "bb.event.ParseStarted",
- "bb.event.ParseProgress", "bb.event.ParseCompleted", "bb.event.CacheLoadStarted",
- "bb.event.CacheLoadProgress", "bb.event.CacheLoadCompleted", "bb.command.CommandFailed",
- "bb.command.CommandExit", "bb.command.CommandCompleted", "bb.cooker.CookerExit",
- "bb.event.MultipleProviders", "bb.event.NoProvider", "bb.runqueue.sceneQueueTaskStarted",
- "bb.runqueue.runQueueTaskStarted", "bb.runqueue.runQueueTaskFailed", "bb.runqueue.sceneQueueTaskFailed",
- "bb.event.BuildBase", "bb.build.TaskStarted", "bb.build.TaskSucceeded", "bb.build.TaskFailedSilent",
- "bb.event.SanityCheckPassed", "bb.event.SanityCheckFailed", "bb.event.PackageInfo",
- "bb.event.TargetsTreeGenerated", "bb.event.ConfigFilesFound", "bb.event.ConfigFilePathFound",
- "bb.event.FilesMatchingFound", "bb.event.NetworkTestFailed", "bb.event.NetworkTestPassed",
- "bb.event.BuildStarted", "bb.event.BuildCompleted", "bb.event.DiskFull"]
-
-def main (server, eventHandler, params):
- params.updateFromServer(server)
- gobject.threads_init()
-
- # That indicates whether the Hob and the bitbake server are
- # running on different machines
- # recipe model and package model
- recipe_model = RecipeListModel()
- package_model = PackageListModel()
-
- llevel, debug_domains = bb.msg.constructLogOptions()
- server.runCommand(["setEventMask", server.getEventHandle(), llevel, debug_domains, _evt_list])
- hobHandler = HobHandler(server, recipe_model, package_model)
- builder = Builder(hobHandler, recipe_model, package_model)
-
- # This timeout function regularly probes the event queue to find out if we
- # have any messages waiting for us.
- gobject.timeout_add(10, event_handle_idle_func, eventHandler, hobHandler)
-
- try:
- gtk.main()
- except EnvironmentError as ioerror:
- # ignore interrupted io
- if ioerror.args[0] == 4:
- pass
- finally:
- hobHandler.cancel_build(force = True)
-
-if __name__ == "__main__":
- try:
- ret = main()
- except Exception:
- ret = 1
- import traceback
- traceback.print_exc(15)
- sys.exit(ret)
diff --git a/yocto-poky/bitbake/lib/bb/ui/knotty.py b/yocto-poky/bitbake/lib/bb/ui/knotty.py
index 90c318376..268562770 100644
--- a/yocto-poky/bitbake/lib/bb/ui/knotty.py
+++ b/yocto-poky/bitbake/lib/bb/ui/knotty.py
@@ -104,10 +104,11 @@ class InteractConsoleLogFilter(logging.Filter):
return True
class TerminalFilter(object):
+ rows = 25
columns = 80
def sigwinch_handle(self, signum, frame):
- self.columns = self.getTerminalColumns()
+ self.rows, self.columns = self.getTerminalColumns()
if self._sigwinch_default:
self._sigwinch_default(signum, frame)
@@ -131,7 +132,7 @@ class TerminalFilter(object):
cr = (env['LINES'], env['COLUMNS'])
except:
cr = (25, 80)
- return cr[1]
+ return cr
def __init__(self, main, helper, console, errconsole, format):
self.main = main
@@ -170,9 +171,13 @@ class TerminalFilter(object):
signal.signal(signal.SIGWINCH, self.sigwinch_handle)
except:
pass
- self.columns = self.getTerminalColumns()
+ self.rows, self.columns = self.getTerminalColumns()
except:
self.cuu = None
+ if not self.cuu:
+ self.interactive = False
+ bb.note("Unable to use interactive mode for this terminal, using fallback")
+ return
console.addFilter(InteractConsoleLogFilter(self, format))
errconsole.addFilter(InteractConsoleLogFilter(self, format))
@@ -207,7 +212,7 @@ class TerminalFilter(object):
content = "Currently %s running tasks (%s of %s):" % (len(activetasks), self.helper.tasknumber_current, self.helper.tasknumber_total)
print(content)
lines = 1 + int(len(content) / (self.columns + 1))
- for tasknum, task in enumerate(tasks):
+ for tasknum, task in enumerate(tasks[:(self.rows - 2)]):
content = "%s: %s" % (tasknum, task)
print(content)
lines = lines + 1 + int(len(content) / (self.columns + 1))
@@ -267,6 +272,8 @@ def main(server, eventHandler, params, tf = TerminalFilter):
logger.addHandler(console)
logger.addHandler(errconsole)
+ bb.utils.set_process_name("KnottyUI")
+
if params.options.remote_server and params.options.kill_server:
server.terminateServer()
return
@@ -282,6 +289,7 @@ def main(server, eventHandler, params, tf = TerminalFilter):
llevel, debug_domains = bb.msg.constructLogOptions()
server.runCommand(["setEventMask", server.getEventHandle(), llevel, debug_domains, _evt_list])
+ universe = False
if not params.observe_only:
params.updateFromServer(server)
params.updateToServer(server, os.environ.copy())
@@ -292,6 +300,8 @@ def main(server, eventHandler, params, tf = TerminalFilter):
if 'msg' in cmdline and cmdline['msg']:
logger.error(cmdline['msg'])
return 1
+ if cmdline['action'][0] == "buildTargets" and "universe" in cmdline['action'][1]:
+ universe = True
ret, error = server.runCommand(cmdline['action'])
if error:
@@ -349,11 +359,20 @@ def main(server, eventHandler, params, tf = TerminalFilter):
return_value = 1
elif event.levelno == format.WARNING:
warnings = warnings + 1
- # For "normal" logging conditions, don't show note logs from tasks
- # but do show them if the user has changed the default log level to
- # include verbose/debug messages
- if event.taskpid != 0 and event.levelno <= format.NOTE and (event.levelno < llevel or (event.levelno == format.NOTE and llevel != format.VERBOSE)):
- continue
+
+ if event.taskpid != 0:
+ # For "normal" logging conditions, don't show note logs from tasks
+ # but do show them if the user has changed the default log level to
+ # include verbose/debug messages
+ if event.levelno <= format.NOTE and (event.levelno < llevel or (event.levelno == format.NOTE and llevel != format.VERBOSE)):
+ continue
+
+ # Prefix task messages with recipe/task
+ if event.taskpid in helper.running_tasks:
+ taskinfo = helper.running_tasks[event.taskpid]
+ event.msg = taskinfo['title'] + ': ' + event.msg
+ if hasattr(event, 'fn'):
+ event.msg = event.fn + ': ' + event.msg
logger.handle(event)
continue
@@ -434,11 +453,12 @@ def main(server, eventHandler, params, tf = TerminalFilter):
logger.info("multiple providers are available for %s%s (%s)", event._is_runtime and "runtime " or "",
event._item,
", ".join(event._candidates))
- logger.info("consider defining a PREFERRED_PROVIDER entry to match %s", event._item)
+ rtime = ""
+ if event._is_runtime:
+ rtime = "R"
+ logger.info("consider defining a PREFERRED_%sPROVIDER entry to match %s" % (rtime, event._item))
continue
if isinstance(event, bb.event.NoProvider):
- return_value = 1
- errors = errors + 1
if event._runtime:
r = "R"
else:
@@ -449,13 +469,20 @@ def main(server, eventHandler, params, tf = TerminalFilter):
if event._close_matches:
extra = ". Close matches:\n %s" % '\n '.join(event._close_matches)
+ # For universe builds, only show these as warnings, not errors
+ h = logger.warning
+ if not universe:
+ return_value = 1
+ errors = errors + 1
+ h = logger.error
+
if event._dependees:
- logger.error("Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)%s", r, event._item, ", ".join(event._dependees), r, extra)
+ h("Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)%s", r, event._item, ", ".join(event._dependees), r, extra)
else:
- logger.error("Nothing %sPROVIDES '%s'%s", r, event._item, extra)
+ h("Nothing %sPROVIDES '%s'%s", r, event._item, extra)
if event._reasons:
for reason in event._reasons:
- logger.error("%s", reason)
+ h("%s", reason)
continue
if isinstance(event, bb.runqueue.sceneQueueTaskStarted):
@@ -475,6 +502,7 @@ def main(server, eventHandler, params, tf = TerminalFilter):
continue
if isinstance(event, bb.runqueue.runQueueTaskFailed):
+ return_value = 1
taskfailures.append(event.taskstring)
logger.error("Task %s (%s) failed with exit code '%s'",
event.taskid, event.taskstring, event.exitcode)
@@ -532,10 +560,12 @@ def main(server, eventHandler, params, tf = TerminalFilter):
main.shutdown = main.shutdown + 1
pass
except Exception as e:
- sys.stderr.write(str(e))
+ import traceback
+ sys.stderr.write(traceback.format_exc())
if not params.observe_only:
_, error = server.runCommand(["stateForceShutdown"])
main.shutdown = 2
+ return_value = 1
try:
summary = ""
if taskfailures:
diff --git a/yocto-poky/bitbake/lib/bb/ui/puccho.py b/yocto-poky/bitbake/lib/bb/ui/puccho.py
deleted file mode 100644
index 3ce4590c1..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/puccho.py
+++ /dev/null
@@ -1,425 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2008 Intel Corporation
-#
-# Authored by Rob Bradford <rob@linux.intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-import gtk
-import gobject
-import gtk.glade
-import threading
-import urllib2
-import os
-import contextlib
-
-from bb.ui.crumbs.buildmanager import BuildManager, BuildConfiguration
-from bb.ui.crumbs.buildmanager import BuildManagerTreeView
-
-from bb.ui.crumbs.runningbuild import RunningBuild, RunningBuildTreeView
-
-# The metadata loader is used by the BuildSetupDialog to download the
-# available options to populate the dialog
-class MetaDataLoader(gobject.GObject):
- """ This class provides the mechanism for loading the metadata (the
- fetching and parsing) from a given URL. The metadata encompasses details
- on what machines are available. The distribution and images available for
- the machine and the the uris to use for building the given machine."""
- __gsignals__ = {
- 'success' : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- 'error' : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_STRING,))
- }
-
- # We use these little helper functions to ensure that we take the gdk lock
- # when emitting the signal. These functions are called as idles (so that
- # they happen in the gtk / main thread's main loop.
- def emit_error_signal (self, remark):
- gtk.gdk.threads_enter()
- self.emit ("error", remark)
- gtk.gdk.threads_leave()
-
- def emit_success_signal (self):
- gtk.gdk.threads_enter()
- self.emit ("success")
- gtk.gdk.threads_leave()
-
- def __init__ (self):
- gobject.GObject.__init__ (self)
-
- class LoaderThread(threading.Thread):
- """ This class provides an asynchronous loader for the metadata (by
- using threads and signals). This is useful since the metadata may be
- at a remote URL."""
- class LoaderImportException (Exception):
- pass
-
- def __init__(self, loader, url):
- threading.Thread.__init__ (self)
- self.url = url
- self.loader = loader
-
- def run (self):
- result = {}
- try:
- with contextlib.closing (urllib2.urlopen (self.url)) as f:
- # Parse the metadata format. The format is....
- # <machine>;<default distro>|<distro>...;<default image>|<image>...;<type##url>|...
- for line in f:
- components = line.split(";")
- if (len (components) < 4):
- raise MetaDataLoader.LoaderThread.LoaderImportException
- machine = components[0]
- distros = components[1].split("|")
- images = components[2].split("|")
- urls = components[3].split("|")
-
- result[machine] = (distros, images, urls)
-
- # Create an object representing this *potential*
- # configuration. It can become concrete if the machine, distro
- # and image are all chosen in the UI
- configuration = BuildConfiguration()
- configuration.metadata_url = self.url
- configuration.machine_options = result
- self.loader.configuration = configuration
-
- # Emit that we've actually got a configuration
- gobject.idle_add (MetaDataLoader.emit_success_signal,
- self.loader)
-
- except MetaDataLoader.LoaderThread.LoaderImportException as e:
- gobject.idle_add (MetaDataLoader.emit_error_signal, self.loader,
- "Repository metadata corrupt")
- except Exception as e:
- gobject.idle_add (MetaDataLoader.emit_error_signal, self.loader,
- "Unable to download repository metadata")
- print(e)
-
- def try_fetch_from_url (self, url):
- # Try and download the metadata. Firing a signal if successful
- thread = MetaDataLoader.LoaderThread(self, url)
- thread.start()
-
-class BuildSetupDialog (gtk.Dialog):
- RESPONSE_BUILD = 1
-
- # A little helper method that just sets the states on the widgets based on
- # whether we've got good metadata or not.
- def set_configurable (self, configurable):
- if (self.configurable == configurable):
- return
-
- self.configurable = configurable
- for widget in self.conf_widgets:
- widget.set_sensitive (configurable)
-
- if not configurable:
- self.machine_combo.set_active (-1)
- self.distribution_combo.set_active (-1)
- self.image_combo.set_active (-1)
-
- # GTK widget callbacks
- def refresh_button_clicked (self, button):
- # Refresh button clicked.
-
- url = self.location_entry.get_chars (0, -1)
- self.loader.try_fetch_from_url(url)
-
- def repository_entry_editable_changed (self, entry):
- if (len (entry.get_chars (0, -1)) > 0):
- self.refresh_button.set_sensitive (True)
- else:
- self.refresh_button.set_sensitive (False)
- self.clear_status_message()
-
- # If we were previously configurable we are no longer since the
- # location entry has been changed
- self.set_configurable (False)
-
- def machine_combo_changed (self, combobox):
- active_iter = combobox.get_active_iter()
-
- if not active_iter:
- return
-
- model = combobox.get_model()
-
- if model:
- chosen_machine = model.get (active_iter, 0)[0]
-
- (distros_model, images_model) = \
- self.loader.configuration.get_distro_and_images_models (chosen_machine)
-
- self.distribution_combo.set_model (distros_model)
- self.image_combo.set_model (images_model)
-
- # Callbacks from the loader
- def loader_success_cb (self, loader):
- self.status_image.set_from_icon_name ("info",
- gtk.ICON_SIZE_BUTTON)
- self.status_image.show()
- self.status_label.set_label ("Repository metadata successfully downloaded")
-
- # Set the models on the combo boxes based on the models generated from
- # the configuration that the loader has created
-
- # We just need to set the machine here, that then determines the
- # distro and image options. Cunning huh? :-)
-
- self.configuration = self.loader.configuration
- model = self.configuration.get_machines_model ()
- self.machine_combo.set_model (model)
-
- self.set_configurable (True)
-
- def loader_error_cb (self, loader, message):
- self.status_image.set_from_icon_name ("error",
- gtk.ICON_SIZE_BUTTON)
- self.status_image.show()
- self.status_label.set_text ("Error downloading repository metadata")
- for widget in self.conf_widgets:
- widget.set_sensitive (False)
-
- def clear_status_message (self):
- self.status_image.hide()
- self.status_label.set_label (
- """<i>Enter the repository location and press _Refresh</i>""")
-
- def __init__ (self):
- gtk.Dialog.__init__ (self)
-
- # Cancel
- self.add_button (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
-
- # Build
- button = gtk.Button ("_Build", None, True)
- image = gtk.Image ()
- image.set_from_stock (gtk.STOCK_EXECUTE, gtk.ICON_SIZE_BUTTON)
- button.set_image (image)
- self.add_action_widget (button, BuildSetupDialog.RESPONSE_BUILD)
- button.show_all ()
-
- # Pull in *just* the table from the Glade XML data.
- gxml = gtk.glade.XML (os.path.dirname(__file__) + "/crumbs/puccho.glade",
- root = "build_table")
- table = gxml.get_widget ("build_table")
- self.vbox.pack_start (table, True, False, 0)
-
- # Grab all the widgets that we need to turn on/off when we refresh...
- self.conf_widgets = []
- self.conf_widgets += [gxml.get_widget ("machine_label")]
- self.conf_widgets += [gxml.get_widget ("distribution_label")]
- self.conf_widgets += [gxml.get_widget ("image_label")]
- self.conf_widgets += [gxml.get_widget ("machine_combo")]
- self.conf_widgets += [gxml.get_widget ("distribution_combo")]
- self.conf_widgets += [gxml.get_widget ("image_combo")]
-
- # Grab the status widgets
- self.status_image = gxml.get_widget ("status_image")
- self.status_label = gxml.get_widget ("status_label")
-
- # Grab the refresh button and connect to the clicked signal
- self.refresh_button = gxml.get_widget ("refresh_button")
- self.refresh_button.connect ("clicked", self.refresh_button_clicked)
-
- # Grab the location entry and connect to editable::changed
- self.location_entry = gxml.get_widget ("location_entry")
- self.location_entry.connect ("changed",
- self.repository_entry_editable_changed)
-
- # Grab the machine combo and hook onto the changed signal. This then
- # allows us to populate the distro and image combos
- self.machine_combo = gxml.get_widget ("machine_combo")
- self.machine_combo.connect ("changed", self.machine_combo_changed)
-
- # Setup the combo
- cell = gtk.CellRendererText()
- self.machine_combo.pack_start(cell, True)
- self.machine_combo.add_attribute(cell, 'text', 0)
-
- # Grab the distro and image combos. We need these to populate with
- # models once the machine is chosen
- self.distribution_combo = gxml.get_widget ("distribution_combo")
- cell = gtk.CellRendererText()
- self.distribution_combo.pack_start(cell, True)
- self.distribution_combo.add_attribute(cell, 'text', 0)
-
- self.image_combo = gxml.get_widget ("image_combo")
- cell = gtk.CellRendererText()
- self.image_combo.pack_start(cell, True)
- self.image_combo.add_attribute(cell, 'text', 0)
-
- # Put the default descriptive text in the status box
- self.clear_status_message()
-
- # Mark as non-configurable, this is just greys out the widgets the
- # user can't yet use
- self.configurable = False
- self.set_configurable(False)
-
- # Show the table
- table.show_all ()
-
- # The loader and some signals connected to it to update the status
- # area
- self.loader = MetaDataLoader()
- self.loader.connect ("success", self.loader_success_cb)
- self.loader.connect ("error", self.loader_error_cb)
-
- def update_configuration (self):
- """ A poorly named function but it updates the internal configuration
- from the widgets. This can make that configuration concrete and can
- thus be used for building """
- # Extract the chosen machine from the combo
- model = self.machine_combo.get_model()
- active_iter = self.machine_combo.get_active_iter()
- if (active_iter):
- self.configuration.machine = model.get(active_iter, 0)[0]
-
- # Extract the chosen distro from the combo
- model = self.distribution_combo.get_model()
- active_iter = self.distribution_combo.get_active_iter()
- if (active_iter):
- self.configuration.distro = model.get(active_iter, 0)[0]
-
- # Extract the chosen image from the combo
- model = self.image_combo.get_model()
- active_iter = self.image_combo.get_active_iter()
- if (active_iter):
- self.configuration.image = model.get(active_iter, 0)[0]
-
-# This function operates to pull events out from the event queue and then push
-# them into the RunningBuild (which then drives the RunningBuild which then
-# pushes through and updates the progress tree view.)
-#
-# TODO: Should be a method on the RunningBuild class
-def event_handle_timeout (eventHandler, build):
- # Consume as many messages as we can ...
- event = eventHandler.getEvent()
- while event:
- build.handle_event (event)
- event = eventHandler.getEvent()
- return True
-
-class MainWindow (gtk.Window):
-
- # Callback that gets fired when the user hits a button in the
- # BuildSetupDialog.
- def build_dialog_box_response_cb (self, dialog, response_id):
- conf = None
- if (response_id == BuildSetupDialog.RESPONSE_BUILD):
- dialog.update_configuration()
- print(dialog.configuration.machine, dialog.configuration.distro, \
- dialog.configuration.image)
- conf = dialog.configuration
-
- dialog.destroy()
-
- if conf:
- self.manager.do_build (conf)
-
- def build_button_clicked_cb (self, button):
- dialog = BuildSetupDialog ()
-
- # For some unknown reason Dialog.run causes nice little deadlocks ... :-(
- dialog.connect ("response", self.build_dialog_box_response_cb)
- dialog.show()
-
- def __init__ (self):
- gtk.Window.__init__ (self)
-
- # Pull in *just* the main vbox from the Glade XML data and then pack
- # that inside the window
- gxml = gtk.glade.XML (os.path.dirname(__file__) + "/crumbs/puccho.glade",
- root = "main_window_vbox")
- vbox = gxml.get_widget ("main_window_vbox")
- self.add (vbox)
-
- # Create the tree views for the build manager view and the progress view
- self.build_manager_view = BuildManagerTreeView()
- self.running_build_view = RunningBuildTreeView()
-
- # Grab the scrolled windows that we put the tree views into
- self.results_scrolledwindow = gxml.get_widget ("results_scrolledwindow")
- self.progress_scrolledwindow = gxml.get_widget ("progress_scrolledwindow")
-
- # Put the tree views inside ...
- self.results_scrolledwindow.add (self.build_manager_view)
- self.progress_scrolledwindow.add (self.running_build_view)
-
- # Hook up the build button...
- self.build_button = gxml.get_widget ("main_toolbutton_build")
- self.build_button.connect ("clicked", self.build_button_clicked_cb)
-
-# I'm not very happy about the current ownership of the RunningBuild. I have
-# my suspicions that this object should be held by the BuildManager since we
-# care about the signals in the manager
-
-def running_build_succeeded_cb (running_build, manager):
- # Notify the manager that a build has succeeded. This is necessary as part
- # of the 'hack' that we use for making the row in the model / view
- # representing the ongoing build change into a row representing the
- # completed build. Since we know only one build can be running a time then
- # we can handle this.
-
- # FIXME: Refactor all this so that the RunningBuild is owned by the
- # BuildManager. It can then hook onto the signals directly and drive
- # interesting things it cares about.
- manager.notify_build_succeeded ()
- print("build succeeded")
-
-def running_build_failed_cb (running_build, manager):
- # As above
- print("build failed")
- manager.notify_build_failed ()
-
-def main (server, eventHandler):
- # Initialise threading...
- gobject.threads_init()
- gtk.gdk.threads_init()
-
- main_window = MainWindow ()
- main_window.show_all ()
-
- # Set up the build manager stuff in general
- builds_dir = os.path.join (os.getcwd(), "results")
- manager = BuildManager (server, builds_dir)
- main_window.build_manager_view.set_model (manager.model)
-
- # Do the running build setup
- running_build = RunningBuild ()
- main_window.running_build_view.set_model (running_build.model)
- running_build.connect ("build-succeeded", running_build_succeeded_cb,
- manager)
- running_build.connect ("build-failed", running_build_failed_cb, manager)
-
- # We need to save the manager into the MainWindow so that the toolbar
- # button can use it.
- # FIXME: Refactor ?
- main_window.manager = manager
-
- # Use a timeout function for probing the event queue to find out if we
- # have a message waiting for us.
- gobject.timeout_add (200,
- event_handle_timeout,
- eventHandler,
- running_build)
-
- gtk.main()
diff --git a/yocto-poky/bitbake/lib/bb/ui/toasterui.py b/yocto-poky/bitbake/lib/bb/ui/toasterui.py
index 3d261503e..6bf4c1f03 100644
--- a/yocto-poky/bitbake/lib/bb/ui/toasterui.py
+++ b/yocto-poky/bitbake/lib/bb/ui/toasterui.py
@@ -92,6 +92,43 @@ def _close_build_log(build_log):
build_log.close()
logger.removeHandler(build_log)
+_evt_list = [
+ "bb.build.TaskBase",
+ "bb.build.TaskFailed",
+ "bb.build.TaskFailedSilent",
+ "bb.build.TaskStarted",
+ "bb.build.TaskSucceeded",
+ "bb.command.CommandCompleted",
+ "bb.command.CommandExit",
+ "bb.command.CommandFailed",
+ "bb.cooker.CookerExit",
+ "bb.event.BuildCompleted",
+ "bb.event.BuildStarted",
+ "bb.event.CacheLoadCompleted",
+ "bb.event.CacheLoadProgress",
+ "bb.event.CacheLoadStarted",
+ "bb.event.ConfigParsed",
+ "bb.event.DepTreeGenerated",
+ "bb.event.LogExecTTY",
+ "bb.event.MetadataEvent",
+ "bb.event.MultipleProviders",
+ "bb.event.NoProvider",
+ "bb.event.ParseCompleted",
+ "bb.event.ParseProgress",
+ "bb.event.RecipeParsed",
+ "bb.event.SanityCheck",
+ "bb.event.SanityCheckPassed",
+ "bb.event.TreeDataPreparationCompleted",
+ "bb.event.TreeDataPreparationStarted",
+ "bb.runqueue.runQueueTaskCompleted",
+ "bb.runqueue.runQueueTaskFailed",
+ "bb.runqueue.runQueueTaskSkipped",
+ "bb.runqueue.runQueueTaskStarted",
+ "bb.runqueue.sceneQueueTaskCompleted",
+ "bb.runqueue.sceneQueueTaskFailed",
+ "bb.runqueue.sceneQueueTaskStarted",
+ "logging.LogRecord"]
+
def main(server, eventHandler, params):
# set to a logging.FileHandler instance when a build starts;
# see _open_build_log()
@@ -115,6 +152,11 @@ def main(server, eventHandler, params):
console.setFormatter(formatter)
logger.addHandler(console)
logger.setLevel(logging.INFO)
+ llevel, debug_domains = bb.msg.constructLogOptions()
+ result, error = server.runCommand(["setEventMask", server.getEventHandle(), llevel, debug_domains, _evt_list])
+ if not result or error:
+ logger.error("can't set event mask: %s", error)
+ return 1
# verify and warn
build_history_enabled = True
@@ -125,8 +167,23 @@ def main(server, eventHandler, params):
build_history_enabled = False
if not params.observe_only:
- logger.error("ToasterUI can only work in observer mode")
- return 1
+ params.updateFromServer(server)
+ params.updateToServer(server, os.environ.copy())
+ cmdline = params.parseActions()
+ if not cmdline:
+ print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
+ return 1
+ if 'msg' in cmdline and cmdline['msg']:
+ logger.error(cmdline['msg'])
+ return 1
+
+ ret, error = server.runCommand(cmdline['action'])
+ if error:
+ logger.error("Command '%s' failed: %s" % (cmdline, error))
+ return 1
+ elif ret != True:
+ logger.error("Command '%s' failed: returned %s" % (cmdline, ret))
+ return 1
# set to 1 when toasterui needs to shut down
main.shutdown = 0
@@ -138,7 +195,8 @@ def main(server, eventHandler, params):
taskfailures = []
first = True
- buildinfohelper = BuildInfoHelper(server, build_history_enabled)
+ buildinfohelper = BuildInfoHelper(server, build_history_enabled,
+ os.getenv('TOASTER_BRBE'))
# write our own log files into bitbake's log directory;
# we're only interested in the path to the parent directory of
@@ -182,12 +240,11 @@ def main(server, eventHandler, params):
continue
if isinstance(event, bb.event.BuildStarted):
- # command-line builds don't fire a ParseStarted event,
- # so we have to start the log file for those on BuildStarted instead
if not (build_log and build_log_file_path):
build_log, build_log_file_path = _open_build_log(log_dir)
buildinfohelper.store_started_build(event, build_log_file_path)
+ continue
if isinstance(event, (bb.build.TaskStarted, bb.build.TaskSucceeded, bb.build.TaskFailedSilent)):
buildinfohelper.update_and_store_task(event)
@@ -315,28 +372,30 @@ def main(server, eventHandler, params):
# update the build info helper on BuildCompleted, not on CommandXXX
buildinfohelper.update_build_information(event, errors, warnings, taskfailures)
+
+ brbe = buildinfohelper.brbe
buildinfohelper.close(errorcode)
- # mark the log output; controllers may kill the toasterUI after seeing this log
- logger.info("ToasterUI build done 1, brbe: %s", buildinfohelper.brbe )
# we start a new build info
- if buildinfohelper.brbe is not None:
- logger.debug("ToasterUI under BuildEnvironment management - exiting after the build")
- server.terminateServer()
- else:
+ if params.observe_only:
logger.debug("ToasterUI prepared for new build")
errors = 0
warnings = 0
taskfailures = []
buildinfohelper = BuildInfoHelper(server, build_history_enabled)
+ else:
+ main.shutdown = 1
- logger.info("ToasterUI build done 2")
+ logger.info("ToasterUI build done, brbe: %s", brbe)
continue
if isinstance(event, (bb.command.CommandCompleted,
bb.command.CommandFailed,
bb.command.CommandExit)):
- errorcode = 0
+ if params.observe_only:
+ errorcode = 0
+ else:
+ main.shutdown = 1
continue
@@ -357,6 +416,10 @@ def main(server, eventHandler, params):
buildinfohelper.update_artifact_image_file(event)
elif event.type == "LicenseManifestPath":
buildinfohelper.store_license_manifest_path(event)
+ elif event.type == "SetBRBE":
+ buildinfohelper.brbe = buildinfohelper._get_data_from_event(event)
+ elif event.type == "OSErrorException":
+ logger.error(event)
else:
logger.error("Unprocessed MetadataEvent %s ", str(event))
continue
@@ -366,19 +429,6 @@ def main(server, eventHandler, params):
main.shutdown = 1
continue
- # ignore
- if isinstance(event, (bb.event.BuildBase,
- bb.event.StampUpdate,
- bb.event.RecipePreFinalise,
- bb.runqueue.runQueueEvent,
- bb.runqueue.runQueueExitWait,
- bb.event.OperationProgress,
- bb.command.CommandFailed,
- bb.command.CommandExit,
- bb.command.CommandCompleted,
- bb.event.ReachableStamps)):
- continue
-
if isinstance(event, bb.event.DepTreeGenerated):
buildinfohelper.store_dependency_information(event)
continue
@@ -399,13 +449,6 @@ def main(server, eventHandler, params):
exception_data = traceback.format_exc()
logger.error("%s\n%s" , e, exception_data)
- _, _, tb = sys.exc_info()
- if tb is not None:
- curr = tb
- while curr is not None:
- logger.error("Error data dump %s\n%s\n" , traceback.format_tb(curr,1), pformat(curr.tb_frame.f_locals))
- curr = curr.tb_next
-
# save them to database, if possible; if it fails, we already logged to console.
try:
buildinfohelper.store_log_exception("%s\n%s" % (str(e), exception_data))
diff --git a/yocto-poky/bitbake/lib/bb/ui/uievent.py b/yocto-poky/bitbake/lib/bb/ui/uievent.py
index 7fc50c759..df093c53c 100644
--- a/yocto-poky/bitbake/lib/bb/ui/uievent.py
+++ b/yocto-poky/bitbake/lib/bb/ui/uievent.py
@@ -24,7 +24,7 @@ server and queue them for the UI to process. This process must be used to avoid
client/server deadlocks.
"""
-import socket, threading, pickle
+import socket, threading, pickle, collections
from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
class BBUIEventQueue:
@@ -44,27 +44,32 @@ class BBUIEventQueue:
server.register_function( self.send_event, "event.sendpickle" )
server.socket.settimeout(1)
- self.EventHandler = None
- count_tries = 0
+ self.EventHandle = None
# the event handler registration may fail here due to cooker being in invalid state
# this is a transient situation, and we should retry a couple of times before
# giving up
- while self.EventHandler == None and count_tries < 5:
- self.EventHandle = self.BBServer.registerEventHandler(self.host, self.port)
+ for count_tries in range(5):
+ ret = self.BBServer.registerEventHandler(self.host, self.port)
- if (self.EventHandle != None):
+ if isinstance(ret, collections.Iterable):
+ self.EventHandle, error = ret
+ else:
+ self.EventHandle = ret
+ error = ""
+
+ if self.EventHandle != None:
break
- bb.warn("Could not register UI event handler %s:%d, retry" % (self.host, self.port))
- count_tries += 1
+ errmsg = "Could not register UI event handler. Error: %s, host %s, "\
+ "port %d" % (error, self.host, self.port)
+ bb.warn("%s, retry" % errmsg)
+
import time
time.sleep(1)
-
-
- if self.EventHandle == None:
- raise Exception("Could not register UI event handler")
+ else:
+ raise Exception(errmsg)
self.server = server
@@ -105,6 +110,7 @@ class BBUIEventQueue:
def startCallbackHandler(self):
self.server.timeout = 1
+ bb.utils.set_process_name("UIEventQueue")
while not self.server.quit:
try:
self.server.handle_request()
diff --git a/yocto-poky/bitbake/lib/bb/ui/uihelper.py b/yocto-poky/bitbake/lib/bb/ui/uihelper.py
index a703387fb..db70b763f 100644
--- a/yocto-poky/bitbake/lib/bb/ui/uihelper.py
+++ b/yocto-poky/bitbake/lib/bb/ui/uihelper.py
@@ -57,44 +57,3 @@ class BBUIHelper:
self.needUpdate = False
return (self.running_tasks, self.failed_tasks)
- def findServerDetails(self):
- import sys
- import optparse
- from bb.server.xmlrpc import BitbakeServerInfo, BitBakeServerConnection
- host = ""
- port = 0
- bind = ""
- parser = optparse.OptionParser(
- usage = """%prog -H host -P port -B bindaddr""")
-
- parser.add_option("-H", "--host", help = "Bitbake server's IP address",
- action = "store", dest = "host", default = None)
-
- parser.add_option("-P", "--port", help = "Bitbake server's Port number",
- action = "store", dest = "port", default = None)
-
- parser.add_option("-B", "--bind", help = "Hob2 local bind address",
- action = "store", dest = "bind", default = None)
-
- options, args = parser.parse_args(sys.argv)
- for key, val in options.__dict__.items():
- if key == 'host' and val:
- host = val
- elif key == 'port' and val:
- port = int(val)
- elif key == 'bind' and val:
- bind = val
-
- if not host or not port or not bind:
- parser.print_usage()
- sys.exit(1)
-
- serverinfo = BitbakeServerInfo(host, port)
- clientinfo = (bind, 0)
- connection = BitBakeServerConnection(serverinfo, clientinfo)
-
- server = connection.connection
- eventHandler = connection.events
-
- return server, eventHandler, host, bind
-
diff --git a/yocto-poky/bitbake/lib/bb/utils.py b/yocto-poky/bitbake/lib/bb/utils.py
index 31ec2b7c9..3544bbe17 100644
--- a/yocto-poky/bitbake/lib/bb/utils.py
+++ b/yocto-poky/bitbake/lib/bb/utils.py
@@ -33,6 +33,7 @@ import fnmatch
import traceback
import errno
import signal
+import ast
from commands import getstatusoutput
from contextlib import contextmanager
from ctypes import cdll
@@ -291,19 +292,26 @@ def _print_trace(body, line):
error.append(' %.4d:%s' % (i, body[i-1].rstrip()))
return error
-def better_compile(text, file, realfile, mode = "exec"):
+def better_compile(text, file, realfile, mode = "exec", lineno = 0):
"""
A better compile method. This method
will print the offending lines.
"""
try:
- return compile(text, file, mode)
+ cache = bb.methodpool.compile_cache(text)
+ if cache:
+ return cache
+ # We can't add to the linenumbers for compile, we can pad to the correct number of blank lines though
+ text2 = "\n" * int(lineno) + text
+ code = compile(text2, realfile, mode)
+ bb.methodpool.compile_cache_add(text, code)
+ return code
except Exception as e:
error = []
# split the text into lines again
body = text.split('\n')
- error.append("Error in compiling python function in %s:\n" % realfile)
- if e.lineno:
+ error.append("Error in compiling python function in %s, line %s:\n" % (realfile, lineno))
+ if hasattr(e, "lineno"):
error.append("The code lines resulting in this error were:")
error.extend(_print_trace(body, e.lineno))
else:
@@ -323,8 +331,10 @@ def _print_exception(t, value, tb, realfile, text, context):
exception = traceback.format_exception_only(t, value)
error.append('Error executing a python function in %s:\n' % realfile)
- # Strip 'us' from the stack (better_exec call)
- tb = tb.tb_next
+ # Strip 'us' from the stack (better_exec call) unless that was where the
+ # error came from
+ if tb.tb_next is not None:
+ tb = tb.tb_next
textarray = text.split('\n')
@@ -353,15 +363,6 @@ def _print_exception(t, value, tb, realfile, text, context):
error.extend(_print_trace(text, tbextract[level+1][1]))
except:
error.append(tbformat[level+1])
- elif "d" in context and tbextract[level+1][2]:
- # Try and find the code in the datastore based on the functionname
- d = context["d"]
- functionname = tbextract[level+1][2]
- text = d.getVar(functionname, True)
- if text:
- error.extend(_print_trace(text.split('\n'), tbextract[level+1][1]))
- else:
- error.append(tbformat[level+1])
else:
error.append(tbformat[level+1])
nexttb = tb.tb_next
@@ -371,7 +372,7 @@ def _print_exception(t, value, tb, realfile, text, context):
finally:
logger.error("\n".join(error))
-def better_exec(code, context, text = None, realfile = "<code>"):
+def better_exec(code, context, text = None, realfile = "<code>", pythonexception=False):
"""
Similiar to better_compile, better_exec will
print the lines that are responsible for the
@@ -388,6 +389,8 @@ def better_exec(code, context, text = None, realfile = "<code>"):
# Error already shown so passthrough, no need for traceback
raise
except Exception as e:
+ if pythonexception:
+ raise
(t, value, tb) = sys.exc_info()
try:
_print_exception(t, value, tb, realfile, text, context)
@@ -533,6 +536,21 @@ def sha256_file(filename):
s.update(line)
return s.hexdigest()
+def sha1_file(filename):
+ """
+ Return the hex string representation of the SHA1 checksum of the filename
+ """
+ try:
+ import hashlib
+ except ImportError:
+ return None
+
+ s = hashlib.sha1()
+ with open(filename, "rb") as f:
+ for line in f:
+ s.update(line)
+ return s.hexdigest()
+
def preserved_envvars_exported():
"""Variables which are taken from the environment and placed in and exported
from the metadata"""
@@ -621,7 +639,7 @@ def build_environment(d):
"""
import bb.data
for var in bb.data.keys(d):
- export = d.getVarFlag(var, "export")
+ export = d.getVarFlag(var, "export", False)
if export:
os.environ[var] = d.getVar(var, True) or ""
@@ -906,6 +924,24 @@ def to_boolean(string, default=None):
raise ValueError("Invalid value for to_boolean: %s" % string)
def contains(variable, checkvalues, truevalue, falsevalue, d):
+ """Check if a variable contains all the values specified.
+
+ Arguments:
+
+ variable -- the variable name. This will be fetched and expanded (using
+ d.getVar(variable, True)) and then split into a set().
+
+ checkvalues -- if this is a string it is split on whitespace into a set(),
+ otherwise coerced directly into a set().
+
+ truevalue -- the value to return if checkvalues is a subset of variable.
+
+ falsevalue -- the value to return if variable is empty or if checkvalues is
+ not a subset of variable.
+
+ d -- the data store.
+ """
+
val = d.getVar(variable, True)
if not val:
return falsevalue
@@ -914,7 +950,7 @@ def contains(variable, checkvalues, truevalue, falsevalue, d):
checkvalues = set(checkvalues.split())
else:
checkvalues = set(checkvalues)
- if checkvalues.issubset(val):
+ if checkvalues.issubset(val):
return truevalue
return falsevalue
@@ -1140,7 +1176,7 @@ def edit_metadata(meta_lines, variables, varfunc, match_overrides=False):
if in_var.endswith('()'):
if full_value.count('{') - full_value.count('}') >= 0:
continue
- full_value = full_value[:-1]
+ full_value = full_value[:-1]
if handle_var_end():
updated = True
checkspc = True
@@ -1385,3 +1421,33 @@ def ioprio_set(who, cls, value):
raise ValueError("Unable to set ioprio, syscall returned %s" % rc)
else:
bb.warn("Unable to set IO Prio for arch %s" % _unamearch)
+
+def set_process_name(name):
+ from ctypes import cdll, byref, create_string_buffer
+ # This is nice to have for debugging, not essential
+ try:
+ libc = cdll.LoadLibrary('libc.so.6')
+ buff = create_string_buffer(len(name)+1)
+ buff.value = name
+ libc.prctl(15, byref(buff), 0, 0, 0)
+ except:
+ pass
+
+# export common proxies variables from datastore to environment
+def export_proxies(d):
+ import os
+
+ variables = ['http_proxy', 'HTTP_PROXY', 'https_proxy', 'HTTPS_PROXY',
+ 'ftp_proxy', 'FTP_PROXY', 'no_proxy', 'NO_PROXY']
+ exported = False
+
+ for v in variables:
+ if v in os.environ.keys():
+ exported = True
+ else:
+ v_proxy = d.getVar(v, True)
+ if v_proxy is not None:
+ os.environ[v] = v_proxy
+ exported = True
+
+ return exported
OpenPOWER on IntegriCloud