summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster/toastergui/views.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/toaster/toastergui/views.py')
-rwxr-xr-xbitbake/lib/toaster/toastergui/views.py91
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"}