Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
Package Reverse Dependency Chain Including USE Flags
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Portage & Programming
View previous topic :: View next topic  
Author Message
nick_0189
n00b
n00b


Joined: 28 Jul 2022
Posts: 15

PostPosted: Fri Apr 11, 2025 2:01 am    Post subject: Package Reverse Dependency Chain Including USE Flags Reply with quote

Hello all,

I would like to map out the reverse dependency chain which causes a given package to be installed on a system, including use flags that would trigger its install. Has this been done before?

I wrote a short python script that can map the reverse dependency chain for an input package, but I am looking at a big time sink for finding if there are any use flags that triggered the inclusion of the package.

Here is the script:

Code:

#!/usr/bin/env python

class DependencyMap:
    def __init__(self, filename):
        file = open(filename)
        text = file.read()
        lines = text.split("\n")

        self.lines = self.clean_lines(lines)
        self.parents = self.find_parents()

    def clean_lines(self, lines):
        start_text = "pulled in by:"
        end_text = ">>>"
        start_flag = False
        end_flag = False
        for line in lines:
            if not start_flag:
                start_flag = start_text in line
            if not start_flag:
                continue
            if start_flag:
                end_flag = end_text in line
            if end_flag:
                break
            yield(line)

    def find_parents(self):
        parents = {}
        parent = (0, "",)
        for line in self.lines:
            if not line.strip():
                continue
            indent = len(line) - len(line.lstrip())
            pkg = line.strip().split(" ")[0]
            parent_indent, parent_pkg = parent
            if not parent_indent or indent <= parent_indent:
                parent = (indent, pkg,)
                continue
            parents.setdefault(parent_pkg, []).append(pkg)
        return(parents)

    def get_input_pkg(self, opts=[]):
        for i,opt in enumerate(opts):
            print(i,opt)
        user_input = input(">>> ")
        if opts:
            return list(opts)[int(user_input)]
        for pkg in self.parents:
            if user_input in pkg:
                opts.append(pkg)
        opts = sorted(list(opts))
        if len(opts) == 1:
            return opts[0]
        return self.get_input_pkg(opts)

    def get_rdep_chain(self, pkg=None, _seen=[], _level=0):
        if pkg is None:
            pkg = self.get_input_pkg()
        yield((_level,pkg,))
        for pkg in self.parents.get(pkg,[]):
            if pkg in _seen:
                continue
            if pkg != "@selected":
                _seen.append(pkg)
            yield from self.get_rdep_chain(pkg, _seen=_seen, _level=_level+1)

def main():
    # emerge --pretend --verbose --emptytree --depclean > emerge_deps.txt
    # portageq metadata / ebuild <PKG> DEPEND

    depMap = DependencyMap("emerge_deps.txt")
    pkg = depMap.get_input_pkg()
    rdepChain = depMap.get_rdep_chain(pkg)
    for level,pkg in rdepChain:
        print("  "*level,pkg)

if __name__ == '__main__':
    main()


It expects an "emerge_deps.txt" file, which can be generated as follows:

Code:

emerge --pretend --verbose --emptytree --depclean > emerge_deps.txt


It can generate the following example output:

Code:

./rdepends.py
>>> brotli
 app-arch/brotli-1.1.0
   app-text/dvisvgm-3.4
     dev-texlive/texlive-binextra-2024_p72338-r1
       app-text/texlive-2024
         @selected
   media-libs/libjxl-0.11.1
     dev-libs/hyprgraphics-0.1.1
       gui-wm/hyprland-0.46.2-r1
         @selected
   media-libs/woff2-1.0.2-r6
   net-libs/libsoup-3.4.4
     gnome-base/gvfs-1.52.3-r1
       xfce-base/thunar-4.20.1
         @selected
     sys-apps/osinfo-db-tools-1.11.0
       sys-apps/osinfo-db-20240701
         sys-libs/libosinfo-1.11.0
           app-emulation/virt-manager-5.0.0-r1
             @selected
   net-libs/nodejs-22.13.1
     @selected
     sys-apps/yarn-1.22.22
       @selected
     www-client/chromium-134.0.6998.117
       @selected
     www-client/firefox-128.8.0
       @selected


This is nice, I can see why a package is required all the way up to the "@selected" packages in the world file, but I would additionally like to know if the package is pulled in by a USE flag or if it is a hard dependency for the package. The USE flag rules for a package can found as follows:

Code:

portageq metadata / ebuild $(qlist -Iv <PKG>) DEPEND


Example output:

Code:

portageq metadata / ebuild $(qlist -Iv grub) DEPEND
app-arch/xz-utils >=sys-libs/ncurses-5.2-r5:0= grub_platforms_emu? ( sdl? ( media-libs/libsdl2 ) ) device-mapper? ( >=sys-fs/lvm2-2.02.45 ) libzfs? ( sys-fs/zfs:= ) mount? ( sys-fs/fuse:3= ) truetype? ( media-libs/freetype:2= ) ppc? ( >=sys-apps/ibm-powerpc-utils-1.3.5 ) ppc64? ( >=sys-apps/ibm-powerpc-utils-1.3.5 )


Portage parses this somehow when determining package dependencies. Is this functionality somewhat independent from Portage so I can pass the active use flags for a given package to a parser to find the triggered dependencies?

For example, I would like to to know that the bluez package is only included under pipewire because the bluetooth USE flag was enabled for pipewire, which was enabled by the desktop profile.

Code:

net-wireless/bluez-5.79
   media-video/pipewire-1.2.7-r2
       (bluetooth? ( dev-libs/glib media-libs/fdk-aac media-libs/libldac media-libs/libfreeaptx media-libs/opus media-libs/sbc >=net-wireless/bluez-4.101:= virtual/libusb:1 )
         /var/db/repos/gentoo/profiles/targets/desktop/make.defaults
     media-video/wireplumber-0.5.8-r2
     sys-apps/xdg-desktop-portal-1.18.4-r1
       x11-base/xwayland-24.1.6
         gui-wm/hyprland-0.46.2-r1
           @selected


Thank you for your help, please let me know if I can clarify anything.
Back to top
View user's profile Send private message
Ralphred
l33t
l33t


Joined: 31 Dec 2013
Posts: 767

PostPosted: Fri Apr 11, 2025 1:14 pm    Post subject: Re: Package Reverse Dependency Chain Including USE Flags Reply with quote

nick_0189 wrote:
Has this been done before?
Not that I'm aware of. There is the equery depgraph command but it's not so tailored as to be able to pass it different use flags and see how a flag switch would affect the whole dependency tree, it does show if something was triggered by a use flag (I think). IIRC it's written in perl(?). I still have a pyqt based frontend for eix* (and equery depgraph) laying around, but the depgraph function was so non-intuitive I shelved it for the "published" version; if you get this working I'd happily use it** as the core of a "show me the dependencies" GUI tab with check boxes for the optional use flags, or even a "compare the dependencies" for multiple packages selected from the search UI.

nick_0189 wrote:
Example output:
Code:
portageq metadata / ebuild $(qlist -Iv grub) DEPEND
app-arch/xz-utils >=sys-libs/ncurses-5.2-r5:0= grub_platforms_emu? ( sdl? ( media-libs/libsdl2 ) ) device-mapper? ( >=sys-fs/lvm2-2.02.45 ) libzfs? ( sys-fs/zfs:= ) mount? ( sys-fs/fuse:3= ) truetype? ( media-libs/freetype:2= ) ppc? ( >=sys-apps/ibm-powerpc-utils-1.3.5 ) ppc64? ( >=sys-apps/ibm-powerpc-utils-1.3.5 )
This doesn't look the easiest to parse, but it's certainly doable. This nesting looks particularly cumbersome to try and convey in an output...
Code:
grub_platforms_emu? ( sdl? ( media-libs/libsdl2 ) )



*eix is extremely well written software, hats off to the dev(s) O7
**with your permission, OFC.
Back to top
View user's profile Send private message
nick_0189
n00b
n00b


Joined: 28 Jul 2022
Posts: 15

PostPosted: Sun Apr 13, 2025 9:27 pm    Post subject: Reply with quote

Thanks for your response. I looked at equery and quse and came to the same conclusion that they could not be used for this. I'll try my hand at writing a parser for the ebuild dependencies and see how it goes, though I've never written a parser before.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Portage & Programming All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum