typeaheads.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. #
  2. # BitBake Toaster Implementation
  3. #
  4. # Copyright (C) 2015 Intel Corporation
  5. #
  6. # SPDX-License-Identifier: GPL-2.0-only
  7. #
  8. import subprocess
  9. from toastergui.widgets import ToasterTypeAhead
  10. from orm.models import Project
  11. from django.urls import reverse
  12. from django.core.cache import cache
  13. class LayersTypeAhead(ToasterTypeAhead):
  14. """ Typeahead for layers available and not added in the current project's
  15. configuration """
  16. def apply_search(self, search_term, prj, request):
  17. layers = prj.get_all_compatible_layer_versions()
  18. layers = layers.order_by('layer__name')
  19. # Unlike the other typeaheads we also don't want to show suggestions
  20. # for layers already in the project unless required such as when adding
  21. # layerdeps to a new layer.
  22. if "include_added" in request.GET and \
  23. request.GET['include_added'] != "true":
  24. layers = layers.exclude(
  25. pk__in=prj.get_project_layer_versions(pk=True))
  26. primary_results = layers.filter(layer__name__istartswith=search_term)
  27. secondary_results = layers.filter(
  28. layer__name__icontains=search_term).exclude(
  29. pk__in=primary_results)
  30. results = []
  31. for layer_version in list(primary_results) + list(secondary_results):
  32. vcs_reference = layer_version.get_vcs_reference()
  33. detail = "[ %s | %s ]" % (layer_version.layer.vcs_url,
  34. vcs_reference)
  35. needed_fields = {
  36. 'id': layer_version.pk,
  37. 'name': layer_version.layer.name,
  38. 'layerdetailurl': layer_version.get_detailspage_url(prj.pk),
  39. 'xhrLayerUrl': reverse('xhr_layer',
  40. args=(prj.pk, layer_version.pk)),
  41. 'vcs_url': layer_version.layer.vcs_url,
  42. 'vcs_reference': vcs_reference,
  43. 'detail': detail,
  44. 'local_source_dir': layer_version.layer.local_source_dir,
  45. }
  46. results.append(needed_fields)
  47. return results
  48. class MachinesTypeAhead(ToasterTypeAhead):
  49. """ Typeahead for all the machines available in the current project's
  50. configuration """
  51. def apply_search(self, search_term, prj, request):
  52. machines = prj.get_available_machines()
  53. machines = machines.order_by("name")
  54. primary_results = machines.filter(name__istartswith=search_term)
  55. secondary_results = machines.filter(
  56. name__icontains=search_term).exclude(pk__in=primary_results)
  57. tertiary_results = machines.filter(
  58. layer_version__layer__name__icontains=search_term).exclude(
  59. pk__in=primary_results).exclude(pk__in=secondary_results)
  60. results = []
  61. for machine in list(primary_results) + list(secondary_results) + \
  62. list(tertiary_results):
  63. detail = "[ %s ]" % (machine.layer_version.layer.name)
  64. needed_fields = {
  65. 'id': machine.pk,
  66. 'name': machine.name,
  67. 'detail': detail,
  68. }
  69. results.append(needed_fields)
  70. return results
  71. class DistrosTypeAhead(ToasterTypeAhead):
  72. """ Typeahead for all the distros available in the current project's
  73. configuration """
  74. def __init__(self):
  75. super(DistrosTypeAhead, self).__init__()
  76. def apply_search(self, search_term, prj, request):
  77. distros = prj.get_available_distros()
  78. distros = distros.order_by("name")
  79. primary_results = distros.filter(name__istartswith=search_term)
  80. secondary_results = distros.filter(name__icontains=search_term).exclude(pk__in=primary_results)
  81. tertiary_results = distros.filter(layer_version__layer__name__icontains=search_term).exclude(pk__in=primary_results).exclude(pk__in=secondary_results)
  82. results = []
  83. for distro in list(primary_results) + list(secondary_results) + list(tertiary_results):
  84. detail = "[ %s ]" % (distro.layer_version.layer.name)
  85. needed_fields = {
  86. 'id' : distro.pk,
  87. 'name' : distro.name,
  88. 'detail' : detail,
  89. }
  90. results.append(needed_fields)
  91. return results
  92. class RecipesTypeAhead(ToasterTypeAhead):
  93. """ Typeahead for all the recipes available in the current project's
  94. configuration """
  95. def apply_search(self, search_term, prj, request):
  96. recipes = prj.get_available_recipes()
  97. recipes = recipes.order_by("name")
  98. primary_results = recipes.filter(name__istartswith=search_term)
  99. secondary_results = recipes.filter(
  100. name__icontains=search_term).exclude(pk__in=primary_results)
  101. tertiary_results = recipes.filter(
  102. layer_version__layer__name__icontains=search_term).exclude(
  103. pk__in=primary_results).exclude(pk__in=secondary_results)
  104. results = []
  105. for recipe in list(primary_results) + list(secondary_results) + \
  106. list(tertiary_results):
  107. detail = "[ %s ]" % (recipe.layer_version.layer.name)
  108. needed_fields = {
  109. 'id': recipe.pk,
  110. 'name': recipe.name,
  111. 'detail': detail,
  112. }
  113. results.append(needed_fields)
  114. return results
  115. class ProjectsTypeAhead(ToasterTypeAhead):
  116. """ Typeahead for all the projects, except for command line builds """
  117. def apply_search(self, search_term, prj, request):
  118. projects = Project.objects.exclude(is_default=True).order_by("name")
  119. primary_results = projects.filter(name__istartswith=search_term)
  120. secondary_results = projects.filter(
  121. name__icontains=search_term).exclude(pk__in=primary_results)
  122. results = []
  123. for project in list(primary_results) + list(secondary_results):
  124. needed_fields = {
  125. 'id': project.pk,
  126. 'name': project.name,
  127. 'detail': "",
  128. 'projectPageUrl': reverse('project', args=(project.pk,))
  129. }
  130. results.append(needed_fields)
  131. return results
  132. class GitRevisionTypeAhead(ToasterTypeAhead):
  133. def apply_search(self, search_term, prj, request):
  134. results = []
  135. git_url = request.GET.get('git_url')
  136. ls_remote = cache.get(git_url)
  137. if ls_remote is None:
  138. ls_remote = subprocess.check_output(['git', 'ls-remote', git_url],
  139. universal_newlines=True)
  140. ls_remote = ls_remote.splitlines()
  141. # Avoid fetching the list of git refs on each new input
  142. cache.set(git_url, ls_remote, 120)
  143. for rev in ls_remote:
  144. git_rev = str(rev).split("/")[-1:][0]
  145. # "HEAD" has a special meaning in Toaster... YOCTO #9924
  146. if "HEAD" in git_rev:
  147. continue
  148. if git_rev.startswith(search_term):
  149. results.append({'name': git_rev,
  150. 'detail': '[ %s ]' % str(rev)})
  151. return results