1# The QDirStat Packages View 2 3QDirStat can now visualize the file lists of installed packages: 4 5![Packages View Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-pkg-details.png) 6 7I.e. files are now grouped by the package they belong to, and in each subtree 8only the files that belong to the package are displayed: In this example, in 9`/usr/bin` only the `chromium-browser` binary is displayed, not all the other 10files in `/usr/bin`. This is intentional. 11 12Notice that you can also see the grouping in the treemap. 13 14A click on the toplevel item in the tree or on `Pkg:/` in the URL shows the 15packages summary: 16 17![Packages Summary Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-pkg-summary.png) 18 19 20 21## Target Platforms 22 23This works on all Linux distributions using one of those low-level package 24managers: 25 26- Dpkg 27- RPM 28- PacMan 29 30...and of course all higher-level package managers that are based on any of 31them. I.e. 32 33- Debian 34 35- Ubuntu / Kubuntu / Xubuntu / Lubuntu 36 37- SUSE (openSUSE Tumbleweed or Leap, SLES) 38 39- Red Hat (Fedora, RHEL) 40 41- Arch Linux 42 43- Manjaro 44 45It can even handle _rpm_ installed as a foreign package manager on a _dpkg_ 46based system (and the other way round); it tries the primary package manager 47first, then any others that are also installed. 48 49Please notice that _apt_, _synaptic_, _zypper_, _pkgkit_ and whatnot are all 50higher level package managers that ultimately use one of the low level ones, so 51even if you only use a higher level package manager, it still works without 52restriction. 53 54 55 56## Package Selection 57 58QDirStat can fetch the information for all installed packages (which may take a 59while) or only for a subset (which is much quicker, of course): 60 61![Screenshot: Packages View limited to "emacs*"](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-pkg-emacs.png) 62 63This example shows all installed packages whose name starts with "emacs". 64 65 66### GUI 67 68Menu _File_ -> _Show Installed Packages_ opens this package selection dialog: 69 70!["Open Packages" Dialog Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-open-pkg-dialog.png) 71 72Enter the search pattern in the input field. The default match mode is _Auto_ 73which tries to guess a reasonable mode, but you can also explicitly select one 74of 75 76- Contains 77- Starts with 78- Exact match 79- Wildcard (very much like in the shell) 80- Regular expression 81 82_Auto_ uses heuristics to make an educated guess. The default is "starts with", 83but if the search pattern contains typical regexp special characters, it 84interprets the pattern as a regular expression. 85 86If it detects just `*` (not `.*`) or `?`, it uses _wildcard_. 87 88If the first character is `=`, it uses _exact match_. 89 90All match modes are case insensitive. 91 92 93### Command Line: Pkg URLs 94 95You can also start QDirStat with a `pkg:` or `pkg:/` URL from the command 96line. This also implicitly uses _auto_ mode, so the same heuristics apply to 97interpret the URL: 98 99``` 100qdirstat pkg:/chrom 101``` 102 103All packages starting with "chrom" or "Chrom" or "CHROM". 104 105_Notice that all patterns are case insensitive -- mostly because distro makers 106and packagers tend to get creative when to use uppercase characters in package 107names, and most users can't remember when or why._ 108 109 110``` 111qdirstat pkg:/=emacs 112``` 113 114Only package "emacs", not "emacs25" or any other starting with "emacs". 115 116 117``` 118qdirstat "pkg:/*gtk*" 119``` 120 121_Notice that you have to protect the `*` wildcards from the shell by escaping 122them with quotes._ 123 124All packages that have "gtk" somewhere in their name. 125 126``` 127qdirstat "pkg:/.*qt[45].*" 128``` 129 130All Qt4 or Qt5 packages. Notice that the patterns are case insensitive. 131 132``` 133qdirstat "pkg:/(firefox|mozilla|chrome|chromium|opera)" 134``` 135 136All the well-known browsers on the system. Notice that regular expressions use 137a partial match, so use the `^` and `$` anchors when appropriate. 138 139 140### Command Line: No initial "Choose Directory" Dialog 141 142If you don't pass a command line argument to QDirStat, it will by default open 143a directory selection dialog. This can be avoided with the `-d` or `--dont-ask` 144command line option: 145 146``` 147qdirstat -d 148``` 149 150Of course you can always simply click that dialog away with the _Cancel_ 151button, but it might be useful for `.desktop` files to have that command line 152parameter. 153 154 155## Behind the Scenes 156 157QDirStat uses external commands to get the information, both the list of 158installed packages and the file list for each of the selected packages. 159 160It always fetches the complete package list and then does the filtering 161internally based on the package filter/URL; it does not rely on how each 162external package manager interprets any patterns. 163 164Packages that are installed in multiple versions or for multiple architectures 165are treated internally as separate packages. 166 167 168To get the package list, QDirStat uses any of those commands: 169 170``` 171dpkg-query --show --showformat='${Package} | ${Version} | ${Architecture} | ${Status}\n' 172``` 173 174``` 175rpm -qa --queryformat '%{name} | %{version}-%{release} | %{arch}\n' 176``` 177 178``` 179pacman -Qn 180``` 181 182Then it parses the output of those commands, removes those that don't fit the 183filter criteria and iterates over the remaining ones to get the file list for 184each one with any of those commands: 185 186``` 187dpkg-query --listfiles pkgname 188``` 189 190``` 191rpm -ql pkgname 192``` 193 194``` 195pacman -Qlq pkgname 196``` 197 198Then for each file list entry QDirStat does the usual `lstat()` syscall to get 199up-to-date information about it from the filesystem (the file lists also don't 200contain any information other than the path, not even if it's a file or a 201directory, much less the size). 202 203As you can imagine, waiting for all those external commands to return 204information takes a while, in particular when all installed packages are 205selected to display. 206 207The first version of this took about 3 minutes to fetch all the information for 208a quite normal Xubuntu 18.04 LTS installation -- much longer than just reading 209the complete root filesystem with cold kernel buffers. 210 211This is why now QDirStat starts a number of those external commands in 212parallel; the sweet spot turned out to be 6 of those processes at the same time 213(whenever one is finished, a new one is started so there are always 6 of them 214running). This improved the speed on the same machine to 54 seconds. 215 216The number of background processes can be configured in 217`~/.config/QDirStat/QDirStat.conf`: 218 219``` 220[Pkg] 221MaxParallelProcesses=6 222``` 223 224For `dpkg` and `rpm` it now uses a single command that fetches the complete 225file list, i.e. all file lists for all installed packages at once. This reduced 226the time on the same machine to 38.5 seconds. 227 228However, this is a tradeoff since fetching that complete file list and parsing 229it takes some time, so this is useful only above a certain number of packages 230(about 200). This limit can be configured in 231 232`~/.config/QDirStat/QDirStat.conf`: 233 234``` 235[Pkg] 236MinCachePkgListSize=200 237``` 238 239Below that, it uses multiple parallel single calls to get individual file 240lists. 241 242Together with more performance tuning it's now down to 6.5 seconds. 243 244 245| sec | Version | Description | 246|------:|------------|---------------------------------------------------------------------| 247| 180.0 | ce3e793298 | First pkg view; sequential separate `dpkg -L` calls | 248| 53.4 | 68038f0525 | Separate `dpkg -L` calls in multiple background processes | 249| 38.5 | ce54879a48 | Single `dpkg -S "*"` call to get all file lists for all pkg at once | 250| 37.7 | 45b0a7a941 | Use cache for `lstat()` syscalls | 251| 24.6 | c50e9a7686 | Use slower update timer for tree view while reading | 252| 6.5 | a1043a20fb | Keep tree collapsed during reading | 253 254See also [GitHub Issue #101](https://github.com/shundhammer/qdirstat/issues/101). 255 256 257## Limitations 258 259### Cleanups 260 261Some of the cleanup actions are still useful in the packages view, in 262particular "Open Filemanager Here" or "Open Terminal Here". 263 264With everything else, be really, really careful! 265 266Since all the files in that display are by definition system files, think twice 267before deleting any one of them. If in doubt, just don't do it. 268 269Be even more careful when dealing with directories: Remember that you only see 270that part of the directory that belongs to that package. There might be many 271more files in such a directory; for most directories, this is almost 272guaranteed. 273 274If you identify a disk space hog with the packages view, it is strongly advised 275that you use your package manager to try to get rid of it, i.e. uninstall that 276package -- and even then only if you know really well what you are doing. 277 278 279### Dependencies 280 281QDirStat only displays the raw information in the packages view: Just the disk 282usage of each package. 283 284It does not and very likely will not display any dependencies of a package, 285much less indirect dependencies. This is the package manager's job. 286 287If you identified a package that uses a lot of disk space, you will very likely 288find that some other package requires it, and yet another package requires that 289one etc. until you get to the level where you can even recognize a package that 290you actively use. 291 292Big fat `libfoo-locale` might be required by `libfoo` which might be required 293by `foomatic` which might be required by `bar-desktop-base` which may be 294required by not only your favourite desktop environment, but also by your 295favourite media player application `boomplayer`. 296 297As a matter of fact, that is more the norm than the exception. Distro makers 298usually don't include packages just for fun, but because they are needed or at 299least useful in the context of your system. 300 301 302### What...if Scenarios 303 304It would have been very nice to to include a feature like "what would happen if 305I tried to remove that package?", showing the user what other packages would 306also need to be removed. 307 308Most higher-level package managers such as `zypper` or `apt` have a _dry run_ 309feature that could be used for this: Try a dry run of removing the `libfoo` 310package, and it will show you all the direct and indirect dependencies, so you 311can make an informed decision if you really can (and want to) live without all 312those packages. 313 314But those commands tend to require root permissions, even for the _dry run_ 315mode, and a desktop program like QDirStat asking for your _sudo_ password to 316get those root permissions might be scary (and for good reasons) to many users. 317 318 319## Support for More Package Managers 320 321It's not that hard to add more package managers to the existing set, but there 322must be reasonable support for that by people who actively use that platform 323and who have the know-how to identify and fix problems. 324 325Check out the existing ones to get an idea; it's little more than copy & paste 326programming. Finding the right external programs and the right parameters is 327the major challenge; then there might be some minor programming work for 328parsing the output. 329 330https://github.com/shundhammer/qdirstat/blob/master/src/RpmPkgManager.h 331https://github.com/shundhammer/qdirstat/blob/master/src/RpmPkgManager.cpp 332 333https://github.com/shundhammer/qdirstat/blob/master/src/DpkgPkgManager.h 334https://github.com/shundhammer/qdirstat/blob/master/src/DpkgPkgManager.cpp 335 336https://github.com/shundhammer/qdirstat/blob/master/src/PacManPkgManager.h 337https://github.com/shundhammer/qdirstat/blob/master/src/PacManPkgManager.cpp 338 339