diff options
author | Elliot Smith <elliot.smith@intel.com> | 2016-01-15 13:00:46 +0200 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2016-01-15 16:29:59 +0000 |
commit | 417f1d3f5306c668e30f2223048b542a46dd5d59 (patch) | |
tree | 8523bf84d908b51745469e83623238fa8c50c83e | |
parent | c02ee05857b67efe879848f379a7e8442c928770 (diff) | |
download | poky-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.py | 68 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/tables.py | 8 | ||||
-rwxr-xr-x | bitbake/lib/toaster/toastergui/views.py | 38 |
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 | |||
29 | from django.conf import settings | 29 | from django.conf import settings |
30 | import django.db.models.signals | 30 | import django.db.models.signals |
31 | 31 | ||
32 | import os.path | ||
33 | import re | ||
34 | |||
32 | import logging | 35 | import logging |
33 | logger = logging.getLogger("toaster") | 36 | logger = 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, |