diff options
| -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, |
