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 ($?) {
- error("A subprocess exited uncleanly (raw: $?)");
+ close($fd);
+ debug_line "\n";
+ waitpid(-1, 0);
+ if ($?) {
+ error("A subprocess exited uncleanly (raw: $?)");
+ }
}
debug(1, 'Read all input');
return if $stream_results;
@@ -348,7 +377,7 @@ sub escape_parens {
my $pattern = shift;
# turn any capturing ( ... ) into non capturing (?: ... )
- $pattern =~ s{ (?<! \\ ) # not preceded by a \
+ $pattern =~ s{ (?<! \\ ) # not preceded by a \
\( # (
(?! \? ) # not followed by a ?
}{(?:}gx;
@@ -357,7 +386,7 @@ sub escape_parens {
sub fix_regexp {
my $pattern = shift;
-
+
# If pattern starts with /, we need to match both ^pattern-without-slash
# (which is put in $pattern) and ^.*pattern (put in $pattern2).
# Later, they will be or'ed together.
@@ -586,6 +615,7 @@ Search filter options:
--architecture -a <arch> Use specific architecture [L]
--index-names -I <names> Only search indices listed in <names> [L]
+ --installed Only search in the installed packages
--filter-suites <suites> Only search indices for the listed <suites> [L]
(E.g. "unstable")
--filter-origins <origins> Only search indices from <origins> [L]
@@ -621,6 +651,7 @@ sub get_options() {
"index-names|I=s" => sub { $_config->set(CONFIG_SEARCH_INDEX_NAMES, $_[1]) },
"verbose|v+" => \$Conf->{verbose},
"ignore-case|i" => \$Conf->{ignore_case},
+ "installed" => \$Conf->{installed},
"regexp|x" => \$Conf->{is_regexp},
"substring-match" => \$Conf->{substring_match},
"package-only|l" => \$Conf->{package_only},
diff --git a/apt-file.pod b/apt-file.pod
index 42143ca..a381ed7 100644
--- a/apt-file.pod
+++ b/apt-file.pod
@@ -171,6 +171,10 @@ Then, apt-file will recognise "deb", "dsc" and "udeb" as index names.
This option defaults to the value of the "apt-file::Index-Names" apt
config option (or "deb" if omitted).
+=item --installed
+
+Only search in the installed packages.
+
=item -i, --ignore-case
Ignore case when searching for pattern.
Reply to: