1# 2# BitBake Toaster Implementation 3# 4# Copyright (C) 2015 Intel Corporation 5# 6# This program is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License version 2 as 8# published by the Free Software Foundation. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License along 16# with this program; if not, write to the Free Software Foundation, Inc., 17# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 19import subprocess 20 21from toastergui.widgets import ToasterTypeAhead 22from orm.models import Project 23from django.core.urlresolvers import reverse 24from django.core.cache import cache 25 26 27class LayersTypeAhead(ToasterTypeAhead): 28 """ Typeahead for layers available and not added in the current project's 29 configuration """ 30 31 def apply_search(self, search_term, prj, request): 32 layers = prj.get_all_compatible_layer_versions() 33 layers = layers.order_by('layer__name') 34 35 # Unlike the other typeaheads we also don't want to show suggestions 36 # for layers already in the project unless required such as when adding 37 # layerdeps to a new layer. 38 if "include_added" in request.GET and \ 39 request.GET['include_added'] != "true": 40 layers = layers.exclude( 41 pk__in=prj.get_project_layer_versions(pk=True)) 42 43 primary_results = layers.filter(layer__name__istartswith=search_term) 44 secondary_results = layers.filter( 45 layer__name__icontains=search_term).exclude( 46 pk__in=primary_results) 47 48 results = [] 49 50 for layer_version in list(primary_results) + list(secondary_results): 51 vcs_reference = layer_version.get_vcs_reference() 52 53 detail = "[ %s | %s ]" % (layer_version.layer.vcs_url, 54 vcs_reference) 55 needed_fields = { 56 'id': layer_version.pk, 57 'name': layer_version.layer.name, 58 'layerdetailurl': layer_version.get_detailspage_url(prj.pk), 59 'xhrLayerUrl': reverse('xhr_layer', 60 args=(prj.pk, layer_version.pk)), 61 'vcs_url': layer_version.layer.vcs_url, 62 'vcs_reference': vcs_reference, 63 'detail': detail, 64 'local_source_dir': layer_version.layer.local_source_dir, 65 } 66 67 results.append(needed_fields) 68 69 return results 70 71 72class MachinesTypeAhead(ToasterTypeAhead): 73 """ Typeahead for all the machines available in the current project's 74 configuration """ 75 76 def apply_search(self, search_term, prj, request): 77 machines = prj.get_available_machines() 78 machines = machines.order_by("name") 79 80 primary_results = machines.filter(name__istartswith=search_term) 81 secondary_results = machines.filter( 82 name__icontains=search_term).exclude(pk__in=primary_results) 83 tertiary_results = machines.filter( 84 layer_version__layer__name__icontains=search_term).exclude( 85 pk__in=primary_results).exclude(pk__in=secondary_results) 86 87 results = [] 88 89 for machine in list(primary_results) + list(secondary_results) + \ 90 list(tertiary_results): 91 92 detail = "[ %s ]" % (machine.layer_version.layer.name) 93 needed_fields = { 94 'id': machine.pk, 95 'name': machine.name, 96 'detail': detail, 97 } 98 99 results.append(needed_fields) 100 return results 101 102 103class DistrosTypeAhead(ToasterTypeAhead): 104 """ Typeahead for all the distros available in the current project's 105 configuration """ 106 def __init__(self): 107 super(DistrosTypeAhead, self).__init__() 108 109 def apply_search(self, search_term, prj, request): 110 distros = prj.get_available_distros() 111 distros = distros.order_by("name") 112 113 primary_results = distros.filter(name__istartswith=search_term) 114 secondary_results = distros.filter(name__icontains=search_term).exclude(pk__in=primary_results) 115 tertiary_results = distros.filter(layer_version__layer__name__icontains=search_term).exclude(pk__in=primary_results).exclude(pk__in=secondary_results) 116 117 results = [] 118 119 for distro in list(primary_results) + list(secondary_results) + list(tertiary_results): 120 121 detail = "[ %s ]" % (distro.layer_version.layer.name) 122 needed_fields = { 123 'id' : distro.pk, 124 'name' : distro.name, 125 'detail' : detail, 126 } 127 128 results.append(needed_fields) 129 130 return results 131 132 133class RecipesTypeAhead(ToasterTypeAhead): 134 """ Typeahead for all the recipes available in the current project's 135 configuration """ 136 def apply_search(self, search_term, prj, request): 137 recipes = prj.get_available_recipes() 138 recipes = recipes.order_by("name") 139 140 primary_results = recipes.filter(name__istartswith=search_term) 141 secondary_results = recipes.filter( 142 name__icontains=search_term).exclude(pk__in=primary_results) 143 tertiary_results = recipes.filter( 144 layer_version__layer__name__icontains=search_term).exclude( 145 pk__in=primary_results).exclude(pk__in=secondary_results) 146 147 results = [] 148 149 for recipe in list(primary_results) + list(secondary_results) + \ 150 list(tertiary_results): 151 152 detail = "[ %s ]" % (recipe.layer_version.layer.name) 153 needed_fields = { 154 'id': recipe.pk, 155 'name': recipe.name, 156 'detail': detail, 157 } 158 159 results.append(needed_fields) 160 161 return results 162 163 164class ProjectsTypeAhead(ToasterTypeAhead): 165 """ Typeahead for all the projects, except for command line builds """ 166 def apply_search(self, search_term, prj, request): 167 projects = Project.objects.exclude(is_default=True).order_by("name") 168 169 primary_results = projects.filter(name__istartswith=search_term) 170 secondary_results = projects.filter( 171 name__icontains=search_term).exclude(pk__in=primary_results) 172 173 results = [] 174 175 for project in list(primary_results) + list(secondary_results): 176 needed_fields = { 177 'id': project.pk, 178 'name': project.name, 179 'detail': "", 180 'projectPageUrl': reverse('project', args=(project.pk,)) 181 } 182 183 results.append(needed_fields) 184 185 return results 186 187 188class GitRevisionTypeAhead(ToasterTypeAhead): 189 def apply_search(self, search_term, prj, request): 190 results = [] 191 git_url = request.GET.get('git_url') 192 ls_remote = cache.get(git_url) 193 194 if ls_remote is None: 195 ls_remote = subprocess.check_output(['git', 'ls-remote', git_url], 196 universal_newlines=True) 197 ls_remote = ls_remote.splitlines() 198 # Avoid fetching the list of git refs on each new input 199 cache.set(git_url, ls_remote, 120) 200 201 for rev in ls_remote: 202 git_rev = str(rev).split("/")[-1:][0] 203 # "HEAD" has a special meaning in Toaster... YOCTO #9924 204 if "HEAD" in git_rev: 205 continue 206 207 if git_rev.startswith(search_term): 208 results.append({'name': git_rev, 209 'detail': '[ %s ]' % str(rev)}) 210 211 return results 212