from django.conf import settings
import django.db.models.signals
+import os.path
+import re
+
import logging
logger = logging.getLogger("toaster")
except (Build.DoesNotExist,IndexError):
return( "not_found" )
+ def get_last_build_extensions(self):
+ """
+ Get list of file name extensions for images produced by the most
+ recent build
+ """
+ last_build = Build.objects.get(pk = self.get_last_build_id())
+ return last_build.get_image_file_extensions()
+
def get_last_imgfiles(self):
build_id = self.get_last_build_id
if (-1 == build_id):
eta += ((eta - self.started_on)*(100-completeper))/completeper
return eta
+ def get_image_file_extensions(self):
+ """
+ Get list of file name extensions for images produced by this build
+ """
+ targets = Target.objects.filter(build_id = self.id)
+ extensions = []
+
+ # pattern to match against file path for building extension string
+ pattern = re.compile('\.([^\.]+?)$')
+
+ for target in targets:
+ if (not target.is_image):
+ continue
+
+ target_image_files = Target_Image_File.objects.filter(target_id = target.id)
+
+ for target_image_file in target_image_files:
+ file_name = os.path.basename(target_image_file.file_name)
+ suffix = ''
+
+ continue_matching = True
+
+ # incrementally extract the suffix from the file path,
+ # checking it against the list of valid suffixes at each
+ # step; if the path is stripped of all potential suffix
+ # parts without matching a valid suffix, this returns all
+ # characters after the first '.' in the file name
+ while continue_matching:
+ matches = pattern.search(file_name)
+
+ if None == matches:
+ continue_matching = False
+ suffix = re.sub('^\.', '', suffix)
+ continue
+ else:
+ suffix = matches.group(1) + suffix
+
+ if suffix in Target_Image_File.SUFFIXES:
+ continue_matching = False
+ continue
+ else:
+ # reduce the file name and try to find the next
+ # segment from the path which might be part
+ # of the suffix
+ file_name = re.sub('.' + matches.group(1), '', file_name)
+ suffix = '.' + suffix
+
+ if not suffix in extensions:
+ extensions.append(suffix)
+
+ return ', '.join(extensions)
def get_sorted_target_list(self):
tgts = Target.objects.filter(build_id = self.id).order_by( 'target' );
return self.get_outcome_text()
def __str__(self):
- return "%s %s %s" % (self.id, self.project, ",".join([t.target for t in self.target_set.all()]))
+ return "%d %s %s" % (self.id, self.project, ",".join([t.target for t in self.target_set.all()]))
# an Artifact is anything that results from a Build, and may be of interest to the user, and is not stored elsewhere
sstate_text = property(get_sstate_text)
def __unicode__(self):
- return "%s(%s) %s:%s" % (self.pk, self.build.pk, self.recipe.name, self.task_name)
+ return "%d(%d) %s:%s" % (self.pk, self.build.pk, self.recipe.name, self.task_name)
class Meta:
ordering = ('order', 'recipe' ,)
return sorted(result, key=lambda x: x.layer.name)
def __unicode__(self):
- 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")
+ 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")
class Meta:
unique_together = ("layer_source", "up_id")
self.queryset = queryset
- # columns: last activity on (updated) - DEFAULT, project (name), release, machine, number of builds, last build outcome, recipe (name), errors, warnings, image files
+ # columns: last activity on (updated) - DEFAULT, project (name), release, machine, number of builds, last build outcome, recipe (name), errors, warnings, image files
def setup_columns(self, *args, **kwargs):
name_template = '''
{% load project_url_tag %}
'''
image_files_template = '''
- {% load projecttags %}
{% if data.get_number_of_builds > 0 and data.get_last_outcome == extra.Build.SUCCEEDED %}
<a href="{% url "builddashboard" data.get_last_build_id %}#images">
- {{fstypes | get_dict_value:data.id}}
+ {{data.get_last_build_extensions}}
</a>
{% endif %}
'''
static_data_template=warnings_template)
self.add_column(title='Image files',
- help_text='',
+ help_text='The root file system types produced by \
+ the last project build',
hideable=True,
orderable=False,
static_data_name='image_files',
context_date,today_begin,yesterday_begin = _add_daterange_context(queryset_all, request, {'started_on','completed_on'})
# set up list of fstypes for each build
- fstypes_map = {};
+ fstypes_map = {}
+
for build in build_info:
- targets = Target.objects.filter( build_id = build.id )
- comma = "";
- extensions = "";
- for t in targets:
- if ( not t.is_image ):
- continue
- tif = Target_Image_File.objects.filter( target_id = t.id )
- for i in tif:
- s=re.sub('.*tar.bz2', 'tar.bz2', i.file_name)
- if s == i.file_name:
- s=re.sub('.*\.', '', i.file_name)
- if None == re.search(s,extensions):
- extensions += comma + s
- comma = ", "
- fstypes_map[build.id]=extensions
+ fstypes_map[build.id] = build.get_image_file_extensions()
# send the data to the template
context = {
# translate the project's build target strings
fstypes_map = {};
for project in project_info:
- try:
- targets = Target.objects.filter( build_id = project.get_last_build_id() )
- comma = "";
- extensions = "";
- for t in targets:
- if ( not t.is_image ):
- continue
- tif = Target_Image_File.objects.filter( target_id = t.id )
- for i in tif:
- s=re.sub('.*tar.bz2', 'tar.bz2', i.file_name)
- if s == i.file_name:
- s=re.sub('.*\.', '', i.file_name)
- if None == re.search(s,extensions):
- extensions += comma + s
- comma = ", "
- fstypes_map[project.id]=extensions
- except (Target.DoesNotExist,IndexError):
- fstypes_map[project.id]=project.get_last_imgfiles
+ fstypes_map[project.id] = project.get_last_build_extensions()
context = {
'mru' : build_mru,