diff options
Diffstat (limited to 'bitbake/lib')
-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"} |