summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster/toastergui
diff options
context:
space:
mode:
authorDave Lerner <dave.lerner@windriver.com>2016-03-24 12:12:11 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-03-26 07:34:58 +0000
commitb036afb53783d8600e505ee5a480a8a9f89a0403 (patch)
tree0961de2ff506cb0ed6e7228bfd03db38915bb588 /bitbake/lib/toaster/toastergui
parent9bf98a935177ce7ac04c830bcecbfc22961c36b8 (diff)
downloadpoky-b036afb53783d8600e505ee5a480a8a9f89a0403.tar.gz
bitbake: toaster: get all dependents for pkg for removal
For customised image package removal change behavior. From: Only display the immediate dependents of the requested package to remove, not the full dependent list, that is dependents of dependents ... Do not remove the displayed dependents, just notify the user of the list. To: Display the complete dependent tree, traversing all reverse dependencies starting from the package to be removed and then it's dependents. Change the modal dialog to note that all of these dependents will be removed automatically. [YOCTO #9121] (Bitbake rev: 1185a5bfe1b05a1b63a927c9583dfc031fdac8a9) Signed-off-by: Dave Lerner <dave.lerner@windriver.com> Signed-off-by: Elliot Smith <elliot.smith@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/toaster/toastergui')
-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"}