Bug#1030935: apt-file: patch proposal for #988105 and change its output to add release and arch

2023-02-10 Thread David Kalnischkies
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

2023-02-09 Thread Patrice Duroux
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

2023-02-09 Thread David Kalnischkies
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

2023-02-09 Thread Patrice Duroux
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 ($?) {
-