diff options
Diffstat (limited to 'bitbake/lib/toaster')
-rwxr-xr-x | bitbake/lib/toaster/toastergui/views.py | 140 |
1 files changed, 98 insertions, 42 deletions
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index c7a782005b..9ad2746881 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py | |||
@@ -2501,11 +2501,12 @@ if True: | |||
2501 | """ | 2501 | """ |
2502 | ReST API to add/remove packages to/from custom recipe. | 2502 | ReST API to add/remove packages to/from custom recipe. |
2503 | 2503 | ||
2504 | Entry point: /xhr_customrecipe/<recipe_id>/packages/ | 2504 | Entry point: /xhr_customrecipe/<recipe_id>/packages/<package_id> |
2505 | 2505 | ||
2506 | Methods: | 2506 | Methods: |
2507 | PUT - Add package to the recipe | 2507 | PUT - Add package to the recipe |
2508 | DELETE - Delete package from the recipe | 2508 | DELETE - Delete package from the recipe |
2509 | GET - Get package information | ||
2509 | 2510 | ||
2510 | Returns: | 2511 | Returns: |
2511 | {"error": "ok"} | 2512 | {"error": "ok"} |
@@ -2518,53 +2519,108 @@ if True: | |||
2518 | return {"error": "Custom recipe with id=%s " | 2519 | return {"error": "Custom recipe with id=%s " |
2519 | "not found" % recipe_id} | 2520 | "not found" % recipe_id} |
2520 | 2521 | ||
2521 | if request.method == 'GET' and not package_id: | 2522 | if package_id: |
2522 | packages = recipe.package_set.values("id", "name", "version") | 2523 | try: |
2523 | 2524 | package = CustomImagePackage.objects.get(id=package_id) | |
2524 | return {"error": "ok", | 2525 | except Package.DoesNotExist: |
2525 | "packages" : list(packages), | 2526 | return {"error": "Package with id=%s " |
2526 | "total" : len(packages) | 2527 | "not found" % package_id} |
2527 | } | ||
2528 | 2528 | ||
2529 | try: | 2529 | if request.method == 'GET': |
2530 | package = Package.objects.get(id=package_id) | 2530 | if not package_id: |
2531 | except Package.DoesNotExist: | 2531 | packages = recipe.get_all_packages().values("id", |
2532 | return {"error": "Package with id=%s " | 2532 | "name", |
2533 | "not found" % package_id} | 2533 | "version") |
2534 | |||
2535 | return {"error": "ok", | ||
2536 | "packages" : list(packages), | ||
2537 | "total" : len(packages) | ||
2538 | } | ||
2539 | else: | ||
2540 | all_current_packages = recipe.get_all_packages() | ||
2541 | |||
2542 | # TODO currently we ignore packgegroups as we don't have a | ||
2543 | # way to deal with them yet. | ||
2544 | |||
2545 | # Dependencies for package which aren't satisfied by the | ||
2546 | # current packages in the custom image recipe | ||
2547 | deps = package.package_dependencies_source.annotate( | ||
2548 | name=F('depends_on__name'), | ||
2549 | pk=F('depends_on__pk'), | ||
2550 | size=F('depends_on__size'), | ||
2551 | ).values("name", "pk", "size").filter( | ||
2552 | ~Q(pk__in=all_current_packages) & | ||
2553 | Q(dep_type=Package_Dependency.TYPE_TRDEPENDS) | ||
2554 | ) | ||
2555 | |||
2556 | # Reverse dependencies which are needed by packages that are | ||
2557 | # in the image | ||
2558 | reverse_deps = package.package_dependencies_target.annotate( | ||
2559 | name=F('package__name'), | ||
2560 | pk=F('package__pk'), | ||
2561 | size=F('package__size'), | ||
2562 | ).values("name", "pk", "size").exclude( | ||
2563 | ~Q(pk__in=all_current_packages) | ||
2564 | ) | ||
2565 | |||
2566 | total_size_deps = 0 | ||
2567 | total_size_reverse_deps = 0 | ||
2568 | |||
2569 | for dep in deps: | ||
2570 | dep['size_formatted'] = \ | ||
2571 | filtered_filesizeformat(dep['size']) | ||
2572 | total_size_deps += dep['size'] | ||
2573 | |||
2574 | for dep in reverse_deps: | ||
2575 | dep['size_formatted'] = \ | ||
2576 | filtered_filesizeformat(dep['size']) | ||
2577 | total_size_reverse_deps += dep['size'] | ||
2578 | |||
2579 | |||
2580 | return {"error": "ok", | ||
2581 | "id": package.pk, | ||
2582 | "name": package.name, | ||
2583 | "version": package.version, | ||
2584 | "unsatisfied_dependencies": list(deps), | ||
2585 | "unsatisfied_dependencies_size": total_size_deps, | ||
2586 | "unsatisfied_dependencies_size_formatted": | ||
2587 | filtered_filesizeformat(total_size_deps), | ||
2588 | "reverse_dependencies": list(reverse_deps), | ||
2589 | "reverse_dependencies_size": total_size_reverse_deps, | ||
2590 | "reverse_dependencies_size_formatted": | ||
2591 | filtered_filesizeformat(total_size_reverse_deps)} | ||
2592 | |||
2593 | included_packages = recipe.includes_set.values_list('pk', flat=True) | ||
2534 | 2594 | ||
2535 | if request.method == 'PUT': | 2595 | if request.method == 'PUT': |
2536 | # As these requests are asynchronous we need to make sure we don't | 2596 | # If we're adding back a package which used to be included in this |
2537 | # already have the package in the image recipe | 2597 | # image all we need to do is remove it from the excludes |
2538 | if recipe.package_set.filter(Q(name=package.name) & | 2598 | if package.pk in included_packages: |
2539 | Q(version=package.version)).count() > 0: | 2599 | try: |
2540 | return {"error" : "Package %s already in recipe" % | 2600 | recipe.excludes_set.remove(package) |
2541 | package.name } | 2601 | return {"error": "ok"} |
2542 | 2602 | except Package.DoesNotExist: | |
2543 | # Make a copy of this package | 2603 | return {"error": |
2544 | dependencies = _get_package_dependencies(package.pk) | 2604 | "Package %s not found in excludes but was in " |
2545 | 2605 | "included list" % package.name} | |
2546 | package = _copy_packge_to_recipe(recipe, package) | 2606 | |
2547 | recipe.package_set.add(package) | 2607 | else: |
2548 | 2608 | recipe.appends_set.add(package) | |
2549 | # Filter out dependencies already in the custom image | 2609 | |
2550 | all_in_image = recipe.package_set.all().values_list('name', | 2610 | return {"error": "ok"} |
2551 | flat=True) | ||
2552 | def in_image(pkg): | ||
2553 | return pkg['name'] not in all_in_image | ||
2554 | |||
2555 | dependencies = filter(in_image, dependencies['runtime_deps']) | ||
2556 | return {"error": "ok", | ||
2557 | "dependencies_needed" : dependencies, | ||
2558 | } | ||
2559 | 2611 | ||
2560 | elif request.method == 'DELETE': | 2612 | elif request.method == 'DELETE': |
2561 | if package in recipe.package_set.all(): | 2613 | try: |
2562 | # note that we are infact deleting the copy of the package | 2614 | # If we're deleting a package which is included we need to |
2563 | package.delete() | 2615 | # Add it to the excludes list. |
2616 | if package.pk in included_packages: | ||
2617 | recipe.excludes_set.add(package) | ||
2618 | else: | ||
2619 | recipe.appends_set.remove(package) | ||
2564 | return {"error": "ok"} | 2620 | return {"error": "ok"} |
2565 | else: | 2621 | except CustomImageRecipe.DoesNotExist: |
2566 | return {"error": "Package '%s' is not in the recipe '%s'" % \ | 2622 | return {"error": "Tried to remove package that wasn't present"} |
2567 | (package.name, recipe.name)} | 2623 | |
2568 | else: | 2624 | else: |
2569 | return {"error": "Method %s is not supported" % request.method} | 2625 | return {"error": "Method %s is not supported" % request.method} |
2570 | 2626 | ||