From 2cf55afb9714827401500c631d95d0fc3a10efdd Mon Sep 17 00:00:00 2001 From: Michael Wood Date: Wed, 4 Nov 2015 15:02:28 +0000 Subject: bitbake: toaster: move CustomImageRecipe generation to API entry point Use the CustomImageRecipe generate_recipe_file_contents to generate the recipe that we build from. Move creation of the dummy layer and recipe object to the point of recipe creation as we need these objects before the build time. Also update the methods to add and remove packages to account for the CustomImageRecipe inheriting from Recipe. (Bitbake rev: f3322567378d6038a00da0fab6c5641a1a8e5409) Signed-off-by: Michael Wood Signed-off-by: brian avery Signed-off-by: Richard Purdie --- .../toaster/bldcontrol/localhostbecontroller.py | 29 ++++--- bitbake/lib/toaster/toastergui/views.py | 90 ++++++++++++++++++---- 2 files changed, 90 insertions(+), 29 deletions(-) diff --git a/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py b/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py index 2dd48d454a..8acf013476 100644 --- a/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py +++ b/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py @@ -240,23 +240,22 @@ class LocalhostBEController(BuildEnvironmentController): conf.write('BBPATH .= ":${LAYERDIR}"\nBBFILES += "${LAYERDIR}/recipes/*.bb"\n') # create recipe - recipe = os.path.join(layerpath, "recipes", "%s.bb" % target.target) - with open(recipe, "w") as recipef: - recipef.write("require %s\n" % customrecipe.base_recipe.file_path) - packages = [pkg.name for pkg in customrecipe.packages.all()] - if packages: - recipef.write('IMAGE_INSTALL = "%s"\n' % ' '.join(packages)) + recipe_path = \ + os.path.join(layerpath, "recipes", "%s.bb" % target.target) + with open(recipe_path, "w") as recipef: + recipef.write(customrecipe.generate_recipe_file_contents()) + + # Update the layer and recipe objects + customrecipe.layer_version.dirpath = layerpath + customrecipe.layer_version.save() + + customrecipe.file_path = recipe_path + customrecipe.save() # create *Layer* objects needed for build machinery to work - layer = Layer.objects.get_or_create(name="Toaster Custom layer", - summary="Layer for custom recipes", - vcs_url="file://%s" % layerpath)[0] - breq = target.req - lver = Layer_Version.objects.get_or_create(project=breq.project, layer=layer, - dirpath=layerpath, build=breq.build)[0] - ProjectLayer.objects.get_or_create(project=breq.project, layercommit=lver, - optional=False) - BRLayer.objects.get_or_create(req=breq, name=layer.name, dirpath=layerpath, + BRLayer.objects.get_or_create(req=target.req, + name=layer.name, + dirpath=layerpath, giturl="file://%s" % layerpath) if os.path.isdir(layerpath): layerlist.append(layerpath) diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index 995937a077..389457daf3 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py @@ -2362,10 +2362,37 @@ if True: # create custom recipe try: + # create layer 'Custom layer' and verion if needed + layer = Layer.objects.get_or_create(name="toaster-custom-images", + summary="Layer for custom recipes", + vcs_url="file:///toaster_created_layer" + )[0] + + lver = Layer_Version.objects.get_or_create( + project=params['project'], + layer=layer, + dirpath='toaster_created_layer', + build=None)[0] + + # Add a dependency on our layer to the base recipe's layer + LayerVersionDependency.objects.get_or_create(layer_version=lver, + depends_on=params["base"].layer_version) + + # Add it to our current project if needed + ProjectLayer.objects.get_or_create(project=params['project'], + layercommit=lver, + optional=False) + + # Create the actual recipe recipe = CustomImageRecipe.objects.create( name=request.POST["name"], base_recipe=params["base"], - project=params["project"]) + project=params["project"], + file_path=request.POST["name"], + license="MIT", + version="0.1", + layer_version=lver) + except Error as err: return {"error": "Can't create custom recipe: %s" % err} @@ -2378,20 +2405,24 @@ if True: # We don't want these packages to be linked to anything because # that underlying data may change e.g. delete a build for package in build.package_set.all(): - # Create the duplicate - package.pk = None - package.save() - # Disassociate the package from the build - package.build = None - package.save() - recipe.packages.add(package) + _copy_packge_to_recipe(recipe, package) else: - logger.warn("No packages found for this base recipe") + logger.debug("No packages found for this base recipe") return {"error": "ok", "url": reverse('customrecipe', args=(params['project'].pk, recipe.id))} + def _copy_packge_to_recipe(recipe, package): + """ copy a package from another recipe """ + package.pk = None + package.save() + # Disassociate the package from the build + package.build = None + package.recipe = recipe + package.save() + return package + @xhr_response def xhr_customrecipe_id(request, recipe_id): """ @@ -2454,8 +2485,12 @@ if True: "not found" % recipe_id} if request.method == 'GET' and not package_id: + packages = recipe.package_set.values("id", "name", "version") + return {"error": "ok", - "packages": list(recipe.packages.values_list('id'))} + "packages" : list(packages), + "total" : len(packages) + } try: package = Package.objects.get(id=package_id) @@ -2464,11 +2499,38 @@ if True: "not found" % package_id} if request.method == 'PUT': - recipe.packages.add(package) - return {"error": "ok"} + # As these requests are asynchronous we need to make sure we don't + # already have the package in the image recipe + if recipe.package_set.filter(Q(name=package.name) & + Q(version=package.version)).count() > 0: + return {"error" : "Package %s already in recipe" % + package.name } + + # Make a copy of this package + dependencies = _get_package_dependencies(package.pk) + + package = _copy_packge_to_recipe(recipe, package) + recipe.package_set.add(package) + + # Filter out dependencies already in the custom image + all_in_image = recipe.package_set.all().values_list('name', + flat=True) + def in_image(pkg): + return pkg['name'] not in all_in_image + + dependencies = filter(in_image, dependencies['runtime_deps']) + return {"error": "ok", + "new_package" : {"id": package.pk, + "url": reverse('xhr_customrecipe_packages', + args=(recipe.pk, package.pk)) + }, + "dependencies_needed" : dependencies, + } + elif request.method == 'DELETE': - if package in recipe.packages.all(): - recipe.packages.remove(package) + if package in recipe.package_set.all(): + # note that we are infact deleting the copy of the package + package.delete() return {"error": "ok"} else: return {"error": "Package '%s' is not in the recipe '%s'" % \ -- cgit v1.2.3-54-g00ecf