Bug#1030935: apt-file: patch proposal for #988105 and change its output to add release and arch
On Thu, Feb 09, 2023 at 07:54:21PM +0100, Patrice Duroux wrote: > Will apt sooner or later provide similar functionality to apt-file? > So that the development would become more integrated/consistent. Maybe, maybe not. Personally, I am not much of a fan of rewriting X in Y for (close to) no reason, but perhaps someone else will and/or a good reason is found. apt-file is rather close/integrated/consistent with the rest of the apt- namespace in so far as it is e.g. directly integrated with 'update' nowadays. Other things in "our" namespace are far more detached… > In a first approach I tried using 'dpkg-query -W' but found 'apt list' more > direct for purposes. How can I get also the release of the installed package: > no > way with 'dpkg-query -W -f '${Package} ${Release} ${Architecture} > ${Status}\n'? You want information which is technically not available anywhere. You see that if you don't install some updates: No tool will have an idea from which release/repository a version came from! It can only guess from where you might have installed a version if it can find the same version online somewhere (in apt the mysterious "now" release will appears in such cases). (While there is semi-frequently talk about recording such and more info at installation time *somewhere* in apt/dpkg/… nothing materialized yet) As said, I have no idea what the code does, so also no idea what it would produce. You might get away with similar guesses or by just not printing the information at all. On a sidenote, dpkg somewhat makes available the Contents of installed packages via -L (list) and -S (search), which probably doesn't work the same way as apt-file, but perhaps it helps anyhow. > By the way, dpkg-query(1) manpage cites 'Origin' as a possible field but it > seems always empty on my system. Origin is a heavily overloaded term (like most others). In dpkg it refers to deb-origin(5) (see also dpkg-vendor(1)). In apt it can refer to the field in a Release file (o= in pinning) or pinning by hostname (Pin: origin). And probably other meanings I forgot^Wrepressed. Best regards David Kalnischkies signature.asc Description: PGP signature
Bug#1030935: apt-file: patch proposal for #988105 and change its output to add release and arch
Many thanks for your advices. Will apt sooner or later provide similar functionality to apt-file? So that the development would become more integrated/consistent. In a first approach I tried using 'dpkg-query -W' but found 'apt list' more direct for purposes. How can I get also the release of the installed package: no way with 'dpkg-query -W -f '${Package} ${Release} ${Architecture} ${Status}\n'? And with the version instead, I have then to know which release provides it. By the way, dpkg-query(1) manpage cites 'Origin' as a possible field but it seems always empty on my system. Maybe I should go back then to this first approach. Patrice
Bug#1030935: apt-file: patch proposal for #988105 and change its output to add release and arch
Hi, On Thu, Feb 09, 2023 at 03:10:39PM +0100, Patrice Duroux wrote: > Dear Maintainer, (Disclaimer: I am not an apt-file, but an apt maintainer) > The first is regarding the sub std_release that I add to match the 'apt list' You are not allowed to use 'apt' in a script. We could change its output any second breaking your ad hoc parsing without any qualms. > that gives 'unstable' even if the apt sources.list is using 'sid' and then 'apt list' for some reason prints the 'Suite' value. I suppose it really shouldn't and pick 'Release' (which is what the sources.list includes, which is either 'Suite' or 'Codename' usually). We might change that (q.e.d. previous paragraph). There is no absolute right answer here, it is a question of UI and the specific use case which you prefer. > accordingly the name of the content files. Is there a better way? (apt API? > metadata file?...) I have no idea about perl & libapt-pkg-perl, but I suppose getting a list of installed packages is such a basic task that it should be possible with it. If you really want to parse a program, dpkg would be the better choice here. Accessing the names of files (including the Content files) is a relatively new feature (like ~2 Debian releases old), so I am not sure how much if any is accessible in perl. Command line wise it would be via 'apt-get indextargets'. You will need this as a) Content files have different filenames in different repositories as they have different storage locations (Debian vs Ubuntu mostly). b) are likely compressed, but if and with what is a configuration detail. c) I have plans, but nothing concrete yet to have apt store files elsewhere and with names where your guessing wouldn't work at all. As I am not sure what apt-file does here and what your (perl) code changes, I have no comment on the patch itself and what effects output changes would have. Best regards David Kalnischkies signature.asc Description: PGP signature
Bug#1030935: apt-file: patch proposal for #988105 and change its output to add release and arch
Package: apt-file Version: 3.3 Severity: wishlist Dear Maintainer, Here is a patch. Working on this proposal some questions come to my mind. The first is regarding the sub std_release that I add to match the 'apt list' that gives 'unstable' even if the apt sources.list is using 'sid' and then accordingly the name of the content files. Is there a better way? (apt API? metadata file?...) I checked the values in the UDD 'packages' table where is used 'sid' and not 'unstable', 'bookworm' and not 'testing' for instance. The second is that it changes the default apt-file output format a bit. Would it be better to use an option for that or introduce a conf file so to not change the current one? Even if I would prefer this be the default on my side. ;-) In addition, this change may be related to some other apt-file issues. Finally, be free to modify this code if considered. Regards, Patrice -- System Information: Debian Release: bookworm/sid APT prefers unstable-debug APT policy: (500, 'unstable-debug'), (500, 'unstable'), (1, 'experimental-debug'), (1, 'experimental') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 6.1.0-3-amd64 (SMP w/12 CPU threads; PREEMPT) Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8), LANGUAGE not set Shell: /bin/sh linked to /usr/bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled Versions of packages apt-file depends on: ii apt 2.5.6 ii libapt-pkg-perl 0.1.40+b2 ii libregexp-assemble-perl 0.38-2 ii perl 5.36.0-7 apt-file recommends no packages. apt-file suggests no packages. -- no debconf information diff --git a/apt-file b/apt-file index 74d40a5..e16fc6c 100755 --- a/apt-file +++ b/apt-file @@ -286,6 +286,30 @@ sub open_data_pipeline { return $read_end; } +sub std_release($) { +my ($release) = @_; +$release = 'unstable' if ($release eq 'sid'); +return $release; +} + +sub pkg_installed { +my %list = (); +if (open(my $OUT,'-|','apt --installed list')) { +while (my $line=<$OUT>) { +$line =~ /^([^\/]+)\/([^ ]+) [^ ]+ ([^ ]+)/; +if (defined($1)) { +my $pkg = $1; +my $arch = $3; +foreach my $release (split(/,/, $2)) { +$list{$pkg.'/'.std_release($release).':'.$arch}=1 if ($release ne 'now'); +} +} +} +close($OUT); +} +return \%list; +} + sub do_grep($$) { my ( $data, $pattern ) = @_; my ( $pkgs, $fname, @cmd, $ret); @@ -294,38 +318,43 @@ sub do_grep($$) { my $regexp = eval { $Conf->{ignore_case} ? qr/${pattern}/i : qr/${pattern}/ }; error($@) if $@; my $matches = 0; +my $is_installed = $Conf->{installed} ? pkg_installed() : {}; my $quick_regexp = escape_parens($regexp); -my $fd = open_data_pipeline($data); my $stream_results = $Conf->{streaming}; -tty_human_status('') if $stream_results; -debug(1, "Pipeline open, waiting for input"); -while (<$fd>) { +foreach my $d (@$data) { +my $fd = open_data_pipeline([$d]); +my $tag = basename($d); +$tag = $tag =~ s/.*_([^_]*)_([^_]*)_Contents-([^.]*)\.[^.]*$// ? std_release($1).':'.$3 : ''; +tty_human_status('') if $stream_results; +debug(1, "Pipeline open, waiting for input"); +while (<$fd>) { -# faster, non-capturing search first -next if !/$quick_regexp/o; +# faster, non-capturing search first +next if !/$quick_regexp/o; -next if !( ( $fname, $pkgs ) = /$regexp/o ); +next if !( ( $fname, $pkgs ) = /$regexp/o ); -debug_line "."; +debug_line "."; -if ($stream_results) { -stream_results("/$fname", map { basename($_) } split(m/,/, $pkgs)); -} else { -# Put leading slash on file name -push(@{ $ret->{"/$fname"} }, - # ... and extract the package name - map { basename($_) } split(m/,/, $pkgs) -); -if (++$matches % 10 == 0) { -tty_human_status("Searching, found $matches results so far ..."); +if ($stream_results) { +stream_results("/$fname", map { basename($_) } split(m/,/, $pkgs)); +} else { +# Put leading slash on file name +$matches = push(@{ $ret->{"/$fname"} }, + # ... and extract the package name + map { !$Conf->{installed} || $is_installed->{basename($_).($tag?'/'.$tag:'')} ? basename($_).($tag?'/'.$tag:'') : () } split(m/,/, $pkgs) +); +if ($matches % 10 == 0) { +tty_human_status("Searching, found $matches results so far ..."); +} } } -} -close($fd); -debug_line "\n"; -waitpid(-1, 0); -if ($?) { -