diff options
Diffstat (limited to 'bitbake/lib/toaster')
-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, |