diff options
Diffstat (limited to 'bitbake/lib/toaster')
| -rwxr-xr-x | bitbake/lib/toaster/toastergui/views.py | 91 |
1 files changed, 79 insertions, 12 deletions
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index 15760b36de..cc7ad17cf1 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py | |||
| @@ -2538,6 +2538,60 @@ if True: | |||
| 2538 | 2538 | ||
| 2539 | return response | 2539 | return response |
| 2540 | 2540 | ||
| 2541 | def _traverse_dependents(next_package_id, rev_deps, all_current_packages, tree_level=0): | ||
| 2542 | """ | ||
| 2543 | Recurse through reverse dependency tree for next_package_id. | ||
| 2544 | Limit the reverse dependency search to packages not already scanned, | ||
| 2545 | that is, not already in rev_deps. | ||
| 2546 | Limit the scan to a depth (tree_level) not exceeding the count of | ||
| 2547 | all packages in the custom image, and if that depth is exceeded | ||
| 2548 | return False, pop out of the recursion, and write a warning | ||
| 2549 | to the log, but this is unlikely, suggesting a dependency loop | ||
| 2550 | not caught by bitbake. | ||
| 2551 | On return, the input/output arg rev_deps is appended with queryset | ||
| 2552 | dictionary elements, annotated for use in the customimage template. | ||
| 2553 | The list has unsorted, but unique elements. | ||
| 2554 | """ | ||
| 2555 | max_dependency_tree_depth = all_current_packages.count() | ||
| 2556 | if tree_level >= max_dependency_tree_depth: | ||
| 2557 | logger.warning( | ||
| 2558 | "The number of reverse dependencies " | ||
| 2559 | "for this package exceeds " + max_dependency_tree_depth + | ||
| 2560 | " and the remaining reverse dependencies will not be removed") | ||
| 2561 | return True | ||
| 2562 | |||
| 2563 | package = CustomImagePackage.objects.get(id=next_package_id) | ||
| 2564 | dependents = \ | ||
| 2565 | package.package_dependencies_target.annotate( | ||
| 2566 | name=F('package__name'), | ||
| 2567 | pk=F('package__pk'), | ||
| 2568 | size=F('package__size'), | ||
| 2569 | ).values("name", "pk", "size").exclude( | ||
| 2570 | ~Q(pk__in=all_current_packages) | ||
| 2571 | ) | ||
| 2572 | |||
| 2573 | for pkg in dependents: | ||
| 2574 | if pkg in rev_deps: | ||
| 2575 | # already seen, skip dependent search | ||
| 2576 | continue | ||
| 2577 | |||
| 2578 | rev_deps.append(pkg) | ||
| 2579 | if (_traverse_dependents( | ||
| 2580 | pkg["pk"], rev_deps, all_current_packages, tree_level+1)): | ||
| 2581 | return True | ||
| 2582 | |||
| 2583 | return False | ||
| 2584 | |||
| 2585 | def _get_all_dependents(package_id, all_current_packages): | ||
| 2586 | """ | ||
| 2587 | Returns sorted list of recursive reverse dependencies for package_id, | ||
| 2588 | as a list of dictionary items, by recursing through dependency | ||
| 2589 | relationships. | ||
| 2590 | """ | ||
| 2591 | rev_deps = [] | ||
| 2592 | _traverse_dependents(package_id, rev_deps, all_current_packages) | ||
| 2593 | rev_deps = sorted(rev_deps, key=lambda x: x["name"]) | ||
| 2594 | return rev_deps | ||
| 2541 | 2595 | ||
| 2542 | @xhr_response | 2596 | @xhr_response |
| 2543 | def xhr_customrecipe_packages(request, recipe_id, package_id): | 2597 | def xhr_customrecipe_packages(request, recipe_id, package_id): |
| @@ -2606,15 +2660,9 @@ if True: | |||
| 2606 | ) | 2660 | ) |
| 2607 | 2661 | ||
| 2608 | # Reverse dependencies which are needed by packages that are | 2662 | # Reverse dependencies which are needed by packages that are |
| 2609 | # in the image | 2663 | # in the image. Recursive search providing all dependents, |
| 2610 | reverse_deps = package.package_dependencies_target.annotate( | 2664 | # not just immediate dependents. |
| 2611 | name=F('package__name'), | 2665 | reverse_deps = _get_all_dependents(package_id, all_current_packages) |
| 2612 | pk=F('package__pk'), | ||
| 2613 | size=F('package__size'), | ||
| 2614 | ).values("name", "pk", "size").exclude( | ||
| 2615 | ~Q(pk__in=all_current_packages) | ||
| 2616 | ) | ||
| 2617 | |||
| 2618 | total_size_deps = 0 | 2666 | total_size_deps = 0 |
| 2619 | total_size_reverse_deps = 0 | 2667 | total_size_reverse_deps = 0 |
| 2620 | 2668 | ||
| @@ -2658,6 +2706,11 @@ if True: | |||
| 2658 | 2706 | ||
| 2659 | else: | 2707 | else: |
| 2660 | recipe.appends_set.add(package) | 2708 | recipe.appends_set.add(package) |
| 2709 | # Make sure that package is not in the excludes set | ||
| 2710 | try: | ||
| 2711 | recipe.excludes_set.remove(package) | ||
| 2712 | except: | ||
| 2713 | pass | ||
| 2661 | # Add the dependencies we think will be added to the recipe | 2714 | # Add the dependencies we think will be added to the recipe |
| 2662 | # as a result of appending this package. | 2715 | # as a result of appending this package. |
| 2663 | # TODO this should recurse down the entire deps tree | 2716 | # TODO this should recurse down the entire deps tree |
| @@ -2668,11 +2721,12 @@ if True: | |||
| 2668 | 2721 | ||
| 2669 | recipe.includes_set.add(cust_package) | 2722 | recipe.includes_set.add(cust_package) |
| 2670 | try: | 2723 | try: |
| 2671 | # when adding the pre-requisite package make sure it's not in the | 2724 | # When adding the pre-requisite package, make |
| 2672 | # excluded list from a prior removal. | 2725 | # sure it's not in the excluded list from a |
| 2726 | # prior removal. | ||
| 2673 | recipe.excludes_set.remove(cust_package) | 2727 | recipe.excludes_set.remove(cust_package) |
| 2674 | except Package.DoesNotExist: | 2728 | except Package.DoesNotExist: |
| 2675 | # Don't care if the package had never been excluded | 2729 | # Don't care if the package had never been excluded |
| 2676 | pass | 2730 | pass |
| 2677 | except: | 2731 | except: |
| 2678 | logger.warning("Could not add package's suggested" | 2732 | logger.warning("Could not add package's suggested" |
| @@ -2688,6 +2742,19 @@ if True: | |||
| 2688 | recipe.excludes_set.add(package) | 2742 | recipe.excludes_set.add(package) |
| 2689 | else: | 2743 | else: |
| 2690 | recipe.appends_set.remove(package) | 2744 | recipe.appends_set.remove(package) |
| 2745 | all_current_packages = recipe.get_all_packages() | ||
| 2746 | reverse_deps_dictlist = _get_all_dependents(package.pk, all_current_packages) | ||
| 2747 | ids = [entry['pk'] for entry in reverse_deps_dictlist] | ||
| 2748 | reverse_deps = CustomImagePackage.objects.filter(id__in=ids) | ||
| 2749 | for r in reverse_deps: | ||
| 2750 | try: | ||
| 2751 | if r.id in included_packages: | ||
| 2752 | recipe.excludes_set.add(r) | ||
| 2753 | else: | ||
| 2754 | recipe.appends_set.remove(r) | ||
| 2755 | except: | ||
| 2756 | pass | ||
| 2757 | |||
| 2691 | return {"error": "ok"} | 2758 | return {"error": "ok"} |
| 2692 | except CustomImageRecipe.DoesNotExist: | 2759 | except CustomImageRecipe.DoesNotExist: |
| 2693 | return {"error": "Tried to remove package that wasn't present"} | 2760 | return {"error": "Tried to remove package that wasn't present"} |
