summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorElliot Smith <elliot.smith@intel.com>2016-01-15 13:00:46 +0200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-01-15 16:29:59 +0000
commit417f1d3f5306c668e30f2223048b542a46dd5d59 (patch)
tree8523bf84d908b51745469e83623238fa8c50c83e
parentc02ee05857b67efe879848f379a7e8442c928770 (diff)
downloadpoky-417f1d3f5306c668e30f2223048b542a46dd5d59.tar.gz
bitbake: toaster: check inferred file suffixes against list of known types
The algorithm for finding the suffix for image files produced by the build doesn't reference a list of known file suffixes, so could be prone to error. Modify how file suffixes are parsed from the file path so that they are compared against a list of known types; if this fails, use the part of the basename of the file path after the first '.' character. Also rationalise the places in the views code where we extract the file name extensions for builds, so they both use the same algorithm (before, the same code was duplicated in two places). [YOCTO #8417] (Bitbake rev: dd1c509696b8ab5e593cc64637060a58e95fcd1f) Signed-off-by: Elliot Smith <elliot.smith@intel.com> Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--bitbake/lib/toaster/orm/models.py68
-rw-r--r--bitbake/lib/toaster/toastergui/tables.py8
-rwxr-xr-xbitbake/lib/toaster/toastergui/views.py38
3 files changed, 73 insertions, 41 deletions
diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py
index 7e0cf9676a..b7975ef865 100644
--- a/bitbake/lib/toaster/orm/models.py
+++ b/bitbake/lib/toaster/orm/models.py
@@ -29,6 +29,9 @@ from django.core import validators
29from django.conf import settings 29from django.conf import settings
30import django.db.models.signals 30import django.db.models.signals
31 31
32import os.path
33import re
34
32import logging 35import logging
33logger = logging.getLogger("toaster") 36logger = logging.getLogger("toaster")
34 37
@@ -234,6 +237,14 @@ class Project(models.Model):
234 except (Build.DoesNotExist,IndexError): 237 except (Build.DoesNotExist,IndexError):
235 return( "not_found" ) 238 return( "not_found" )
236 239
240 def get_last_build_extensions(self):
241 """
242 Get list of file name extensions for images produced by the most
243 recent build
244 """
245 last_build = Build.objects.get(pk = self.get_last_build_id())
246 return last_build.get_image_file_extensions()
247
237 def get_last_imgfiles(self): 248 def get_last_imgfiles(self):
238 build_id = self.get_last_build_id 249 build_id = self.get_last_build_id
239 if (-1 == build_id): 250 if (-1 == build_id):
@@ -376,6 +387,57 @@ class Build(models.Model):
376 eta += ((eta - self.started_on)*(100-completeper))/completeper 387 eta += ((eta - self.started_on)*(100-completeper))/completeper
377 return eta 388 return eta
378 389
390 def get_image_file_extensions(self):
391 """
392 Get list of file name extensions for images produced by this build
393 """
394 targets = Target.objects.filter(build_id = self.id)
395 extensions = []
396
397 # pattern to match against file path for building extension string
398 pattern = re.compile('\.([^\.]+?)$')
399
400 for target in targets:
401 if (not target.is_image):
402 continue
403
404 target_image_files = Target_Image_File.objects.filter(target_id = target.id)
405
406 for target_image_file in target_image_files:
407 file_name = os.path.basename(target_image_file.file_name)
408 suffix = ''
409
410 continue_matching = True
411
412 # incrementally extract the suffix from the file path,
413 # checking it against the list of valid suffixes at each
414 # step; if the path is stripped of all potential suffix
415 # parts without matching a valid suffix, this returns all
416 # characters after the first '.' in the file name
417 while continue_matching:
418 matches = pattern.search(file_name)
419
420 if None == matches:
421 continue_matching = False
422 suffix = re.sub('^\.', '', suffix)
423 continue
424 else:
425 suffix = matches.group(1) + suffix
426
427 if suffix in Target_Image_File.SUFFIXES:
428 continue_matching = False
429 continue
430 else:
431 # reduce the file name and try to find the next
432 # segment from the path which might be part
433 # of the suffix
434 file_name = re.sub('.' + matches.group(1), '', file_name)
435 suffix = '.' + suffix
436
437 if not suffix in extensions:
438 extensions.append(suffix)
439
440 return ', '.join(extensions)
379 441
380 def get_sorted_target_list(self): 442 def get_sorted_target_list(self):
381 tgts = Target.objects.filter(build_id = self.id).order_by( 'target' ); 443 tgts = Target.objects.filter(build_id = self.id).order_by( 'target' );
@@ -418,7 +480,7 @@ class Build(models.Model):
418 return self.get_outcome_text() 480 return self.get_outcome_text()
419 481
420 def __str__(self): 482 def __str__(self):
421 return "%s %s %s" % (self.id, self.project, ",".join([t.target for t in self.target_set.all()])) 483 return "%d %s %s" % (self.id, self.project, ",".join([t.target for t in self.target_set.all()]))
422 484
423 485
424# an Artifact is anything that results from a Build, and may be of interest to the user, and is not stored elsewhere 486# an Artifact is anything that results from a Build, and may be of interest to the user, and is not stored elsewhere
@@ -609,7 +671,7 @@ class Task(models.Model):
609 sstate_text = property(get_sstate_text) 671 sstate_text = property(get_sstate_text)
610 672
611 def __unicode__(self): 673 def __unicode__(self):
612 return "%s(%s) %s:%s" % (self.pk, self.build.pk, self.recipe.name, self.task_name) 674 return "%d(%d) %s:%s" % (self.pk, self.build.pk, self.recipe.name, self.task_name)
613 675
614 class Meta: 676 class Meta:
615 ordering = ('order', 'recipe' ,) 677 ordering = ('order', 'recipe' ,)
@@ -1265,7 +1327,7 @@ class Layer_Version(models.Model):
1265 return sorted(result, key=lambda x: x.layer.name) 1327 return sorted(result, key=lambda x: x.layer.name)
1266 1328
1267 def __unicode__(self): 1329 def __unicode__(self):
1268 return "%s %s (VCS %s, Project %s)" % (self.pk, str(self.layer), self.get_vcs_reference(), self.build.project if self.build is not None else "No project") 1330 return "%d %s (VCS %s, Project %s)" % (self.pk, str(self.layer), self.get_vcs_reference(), self.build.project if self.build is not None else "No project")
1269 1331
1270 class Meta: 1332 class Meta:
1271 unique_together = ("layer_source", "up_id") 1333 unique_together = ("layer_source", "up_id")
diff --git a/bitbake/lib/toaster/toastergui/tables.py b/bitbake/lib/toaster/toastergui/tables.py
index e5cab48c48..cc9b5aef40 100644
--- a/bitbake/lib/toaster/toastergui/tables.py
+++ b/bitbake/lib/toaster/toastergui/tables.py
@@ -661,7 +661,7 @@ class ProjectsTable(ToasterTable):
661 661
662 self.queryset = queryset 662 self.queryset = queryset
663 663
664 # columns: last activity on (updated) - DEFAULT, project (name), release, machine, number of builds, last build outcome, recipe (name), errors, warnings, image files 664 # columns: last activity on (updated) - DEFAULT, project (name), release, machine, number of builds, last build outcome, recipe (name), errors, warnings, image files
665 def setup_columns(self, *args, **kwargs): 665 def setup_columns(self, *args, **kwargs):
666 name_template = ''' 666 name_template = '''
667 {% load project_url_tag %} 667 {% load project_url_tag %}
@@ -767,10 +767,9 @@ class ProjectsTable(ToasterTable):
767 ''' 767 '''
768 768
769 image_files_template = ''' 769 image_files_template = '''
770 {% load projecttags %}
771 {% if data.get_number_of_builds > 0 and data.get_last_outcome == extra.Build.SUCCEEDED %} 770 {% if data.get_number_of_builds > 0 and data.get_last_outcome == extra.Build.SUCCEEDED %}
772 <a href="{% url "builddashboard" data.get_last_build_id %}#images"> 771 <a href="{% url "builddashboard" data.get_last_build_id %}#images">
773 {{fstypes | get_dict_value:data.id}} 772 {{data.get_last_build_extensions}}
774 </a> 773 </a>
775 {% endif %} 774 {% endif %}
776 ''' 775 '''
@@ -848,7 +847,8 @@ class ProjectsTable(ToasterTable):
848 static_data_template=warnings_template) 847 static_data_template=warnings_template)
849 848
850 self.add_column(title='Image files', 849 self.add_column(title='Image files',
851 help_text='', 850 help_text='The root file system types produced by \
851 the last project build',
852 hideable=True, 852 hideable=True,
853 orderable=False, 853 orderable=False,
854 static_data_name='image_files', 854 static_data_name='image_files',
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py
index 4cd7afde7c..8148623a8b 100755
--- a/bitbake/lib/toaster/toastergui/views.py
+++ b/bitbake/lib/toaster/toastergui/views.py
@@ -2008,23 +2008,10 @@ if True:
2008 context_date,today_begin,yesterday_begin = _add_daterange_context(queryset_all, request, {'started_on','completed_on'}) 2008 context_date,today_begin,yesterday_begin = _add_daterange_context(queryset_all, request, {'started_on','completed_on'})
2009 2009
2010 # set up list of fstypes for each build 2010 # set up list of fstypes for each build
2011 fstypes_map = {}; 2011 fstypes_map = {}
2012
2012 for build in build_info: 2013 for build in build_info:
2013 targets = Target.objects.filter( build_id = build.id ) 2014 fstypes_map[build.id] = build.get_image_file_extensions()
2014 comma = "";
2015 extensions = "";
2016 for t in targets:
2017 if ( not t.is_image ):
2018 continue
2019 tif = Target_Image_File.objects.filter( target_id = t.id )
2020 for i in tif:
2021 s=re.sub('.*tar.bz2', 'tar.bz2', i.file_name)
2022 if s == i.file_name:
2023 s=re.sub('.*\.', '', i.file_name)
2024 if None == re.search(s,extensions):
2025 extensions += comma + s
2026 comma = ", "
2027 fstypes_map[build.id]=extensions
2028 2015
2029 # send the data to the template 2016 # send the data to the template
2030 context = { 2017 context = {
@@ -3047,24 +3034,7 @@ if True:
3047 # translate the project's build target strings 3034 # translate the project's build target strings
3048 fstypes_map = {}; 3035 fstypes_map = {};
3049 for project in project_info: 3036 for project in project_info:
3050 try: 3037 fstypes_map[project.id] = project.get_last_build_extensions()
3051 targets = Target.objects.filter( build_id = project.get_last_build_id() )
3052 comma = "";
3053 extensions = "";
3054 for t in targets:
3055 if ( not t.is_image ):
3056 continue
3057 tif = Target_Image_File.objects.filter( target_id = t.id )
3058 for i in tif:
3059 s=re.sub('.*tar.bz2', 'tar.bz2', i.file_name)
3060 if s == i.file_name:
3061 s=re.sub('.*\.', '', i.file_name)
3062 if None == re.search(s,extensions):
3063 extensions += comma + s
3064 comma = ", "
3065 fstypes_map[project.id]=extensions
3066 except (Target.DoesNotExist,IndexError):
3067 fstypes_map[project.id]=project.get_last_imgfiles
3068 3038
3069 context = { 3039 context = {
3070 'mru' : build_mru, 3040 'mru' : build_mru,