summaryrefslogtreecommitdiff
path: root/yocto-poky/bitbake/lib/bb/ui/buildinfohelper.py
diff options
context:
space:
mode:
Diffstat (limited to 'yocto-poky/bitbake/lib/bb/ui/buildinfohelper.py')
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/buildinfohelper.py367
1 files changed, 226 insertions, 141 deletions
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