|
@@ -37,7 +37,7 @@ os.environ["DJANGO_SETTINGS_MODULE"] =\
|
|
|
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 Target_Image_File, BuildArtifact, TargetArtifactFile
|
|
|
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
|
|
@@ -121,6 +121,13 @@ class ORMWrapper(object):
|
|
|
|
|
|
return vars(self)[dictname][key]
|
|
|
|
|
|
+ def get_similar_target_with_image_files(self, target):
|
|
|
+ """
|
|
|
+ Get a Target object "similar" to target; i.e. with the same target
|
|
|
+ name ('core-image-minimal' etc.) and machine.
|
|
|
+ """
|
|
|
+ return target.get_similar_target_with_image_files()
|
|
|
+
|
|
|
def _timestamp_to_datetime(self, secs):
|
|
|
"""
|
|
|
Convert timestamp in seconds to Python datetime
|
|
@@ -678,27 +685,32 @@ class ORMWrapper(object):
|
|
|
file_name = file_name,
|
|
|
file_size = file_size)
|
|
|
|
|
|
- def save_artifact_information_no_dedupe(self, build_obj, file_name, file_size):
|
|
|
+ def save_target_artifact_file(self, target_obj, file_name, file_size):
|
|
|
"""
|
|
|
- Save artifact information without checking for duplicate paths;
|
|
|
- this is used when we are saving data about an artifact which was
|
|
|
- generated by a previous build but which is also relevant to this build,
|
|
|
- e.g. a bzImage file.
|
|
|
+ Save artifact file information for a Target target_obj.
|
|
|
+
|
|
|
+ Note that this doesn't include SDK artifacts, only images and
|
|
|
+ related files (e.g. bzImage).
|
|
|
"""
|
|
|
- BuildArtifact.objects.create(build=build_obj, file_name=file_name,
|
|
|
- file_size=file_size)
|
|
|
+ TargetArtifactFile.objects.create(target=target_obj,
|
|
|
+ file_name=file_name, file_size=file_size)
|
|
|
|
|
|
def save_artifact_information(self, build_obj, file_name, file_size):
|
|
|
- # we skip the image files from other builds
|
|
|
- if Target_Image_File.objects.filter(file_name = file_name).count() > 0:
|
|
|
- return
|
|
|
-
|
|
|
+ """
|
|
|
+ TODO this is currently used to save SDK artifacts to the database,
|
|
|
+ but will be replaced in future once SDK artifacts are associated with
|
|
|
+ Target objects (as they eventually should be)
|
|
|
+ """
|
|
|
# do not update artifacts found in other builds
|
|
|
if BuildArtifact.objects.filter(file_name = file_name).count() > 0:
|
|
|
return
|
|
|
|
|
|
- self.save_artifact_information_no_dedupe(self, build_obj, file_name,
|
|
|
- file_size)
|
|
|
+ # do not update artifact if already a target artifact file for that path
|
|
|
+ if TargetArtifactFile.objects.filter(file_name = file_name).count() > 0:
|
|
|
+ return
|
|
|
+
|
|
|
+ BuildArtifact.objects.create(build=build_obj, file_name=file_name,
|
|
|
+ file_size=file_size)
|
|
|
|
|
|
def create_logmessage(self, log_information):
|
|
|
assert 'build' in log_information
|
|
@@ -1496,7 +1508,7 @@ class BuildInfoHelper(object):
|
|
|
|
|
|
self.orm_wrapper.create_logmessage(log_information)
|
|
|
|
|
|
- def _get_files_from_image_license(self, image_license_manifest_path):
|
|
|
+ def _get_filenames_from_image_license(self, image_license_manifest_path):
|
|
|
"""
|
|
|
Find the FILES line in the image_license.manifest file,
|
|
|
which has the basenames of the bzImage and modules files
|
|
@@ -1567,19 +1579,20 @@ class BuildInfoHelper(object):
|
|
|
|
|
|
OR
|
|
|
|
|
|
- 2. There are no files for the target, so copy them from a
|
|
|
- previous build with the same target + machine.
|
|
|
+ 2. There are no new files for the target (they were already produced by
|
|
|
+ a previous build), so copy them from the most recent previous build with
|
|
|
+ the same target, task and machine.
|
|
|
"""
|
|
|
deploy_dir_image = \
|
|
|
self.server.runCommand(['getVariable', 'DEPLOY_DIR_IMAGE'])[0]
|
|
|
|
|
|
# if there's no DEPLOY_DIR_IMAGE, there aren't going to be
|
|
|
- # any build artifacts, so we can return immediately
|
|
|
+ # any image artifacts, so we can return immediately
|
|
|
if not deploy_dir_image:
|
|
|
return
|
|
|
|
|
|
buildname = self.server.runCommand(['getVariable', 'BUILDNAME'])[0]
|
|
|
- machine = self.server.runCommand(['getVariable', 'MACHINE'])[0]
|
|
|
+ machine = self.server.runCommand(['getVariable', 'MACHINE'])[0]
|
|
|
image_name = self.server.runCommand(['getVariable', 'IMAGE_NAME'])[0]
|
|
|
|
|
|
# location of the image_license.manifest files for this build;
|
|
@@ -1597,7 +1610,10 @@ class BuildInfoHelper(object):
|
|
|
image_file_extensions_unique = set(image_file_extensions.split(' '))
|
|
|
|
|
|
targets = self.internal_state['targets']
|
|
|
+
|
|
|
+ # filter out anything which isn't an image target
|
|
|
image_targets = [target for target in targets if target.is_image]
|
|
|
+
|
|
|
for target in image_targets:
|
|
|
# this is set to True if we find at least one file relating to
|
|
|
# this target; if this remains False after the scan, we copy the
|
|
@@ -1625,16 +1641,17 @@ class BuildInfoHelper(object):
|
|
|
if os.path.isfile(image_license_manifest_path):
|
|
|
has_files = True
|
|
|
|
|
|
- basenames = self._get_files_from_image_license(
|
|
|
+ basenames = self._get_filenames_from_image_license(
|
|
|
image_license_manifest_path)
|
|
|
|
|
|
for basename in basenames:
|
|
|
artifact_path = os.path.join(deploy_dir_image, basename)
|
|
|
artifact_size = os.stat(artifact_path).st_size
|
|
|
|
|
|
- self.orm_wrapper.save_artifact_information_no_dedupe(
|
|
|
- self.internal_state['build'], artifact_path,
|
|
|
- artifact_size)
|
|
|
+ # note that the artifact will only be saved against this
|
|
|
+ # build if it hasn't been already
|
|
|
+ self.orm_wrapper.save_target_artifact_file(target,
|
|
|
+ artifact_path, artifact_size)
|
|
|
|
|
|
# store the license manifest path on the target
|
|
|
# (this file is also created any time an image file is created)
|
|
@@ -1648,7 +1665,10 @@ class BuildInfoHelper(object):
|
|
|
# (via real_image_name); note that we don't have to set
|
|
|
# has_files = True, as searching for the license manifest file
|
|
|
# will already have set it to true if at least one image file was
|
|
|
- # produced
|
|
|
+ # produced; note that the real_image_name includes BUILDNAME, which
|
|
|
+ # in turn includes a timestamp; so if no files were produced for
|
|
|
+ # this timestamp (i.e. the build reused existing image files already
|
|
|
+ # in the directory), no files will be recorded against this target
|
|
|
image_files = self._get_image_files(deploy_dir_image,
|
|
|
real_image_name, image_file_extensions_unique)
|
|
|
|
|
@@ -1657,11 +1677,18 @@ class BuildInfoHelper(object):
|
|
|
target, image_file['path'], image_file['size'])
|
|
|
|
|
|
if not has_files:
|
|
|
- # TODO copy artifact and image files from the
|
|
|
- # most-recently-built Target with the same target + machine
|
|
|
- # as this Target; also copy the license manifest path,
|
|
|
- # as that is treated differently
|
|
|
- pass
|
|
|
+ # copy image files and build artifacts from the
|
|
|
+ # most-recently-built Target with the
|
|
|
+ # same target + machine as this Target; also copy the license
|
|
|
+ # manifest path, as that is not treated as an artifact and needs
|
|
|
+ # to be set separately
|
|
|
+ most_recent = \
|
|
|
+ self.orm_wrapper.get_similar_target_with_image_files(target)
|
|
|
+
|
|
|
+ if most_recent:
|
|
|
+ logger.info('image artifacts for target %s cloned from ' \
|
|
|
+ 'target %s' % (target.pk, most_recent.pk))
|
|
|
+ target.clone_artifacts_from(most_recent)
|
|
|
|
|
|
def close(self, errorcode):
|
|
|
if self.brbe is not None:
|