[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: