[Aptitude-devel] Bug#988220: aptitude: documentation improvements

Christoph Anton Mitterer calestyo at scientia.net
Fri May 7 23:28:23 BST 2021


Source: aptitude
Version: 0.8.13-3
Severity: wishlist


Hey.

I was looking through the documentation, specifically the part about search strings
and may have found some ambiguities or things that would benefit from more
clarification:


1) Searching for strings
Mentiones that most patterns are taken as regular expressions, but it seems it's
nowhere mentioned which (POSIX BRE, ERE, PCRE or something else?) are actually used?




2) There's the paragraph starting with "The characters “!” and “|” have special
meanings within search patterns."

That's IMO a bit confusing:
- The whole paragraph is right in the chapter that talks about the "literal" text
  strings within patterns - so it doesn't feel as if the the ! and | here would
  mean the short-form-versions of ?not() and ?or().
- Of course there's also the | of the regexp itself.
  For the example given, ?description(grand~|oblique), it does not seem that
  ?description() allows another subpattern (like ?description(?or(foo, bar)),
  so one would guess the | and ! here would *not* mean ?or() and ?not?
- OTOH, it doesn't seem they mean the regexp patterns.

So what exactly is it and where can it be used?




3) In "Shorthand for search terms"
"Question marks (“?”) will not end the short form of a term,"
I would add here e.g. "(unlike "~", which will end the term)", as the example
with "~i~napt" above seems to apply.




4) Searches and versions
TBH, I have some difficulties to understand how this *exactly* works.
It kinda seems to miss the "great picture", how the matching is actually performed.

Does it go through the list of all package names (without versions) and
match each of them *then with versions* against the patterns and sub-patterns,
where some of the terms then take any/all versions?

Or is it rather like SQL and joins, that each (sub)pattern produces a list of
(package,version) tuples that are then intersected or unified?

At least I'd suspect it does not go through each single (package,version) tuple
and match (just that) against the pattern, cause that wouldn't work.


Like in the example: ?depends(?version(2\.0))
Is it more like:
a) From inner to outer:
   ?version(2\.0) returns all (package,version) tuples that contain "2.0", and
   ?depends() on that, returns all packages depending on any package of that?
or:
b) From outer to inner:
   Go through the list of all (packages,version) or just (package), for each
   of that:
   add it to the result if it depends on the pattern inside (?version(..))
   and then... well no idea?
   
   The explanation of that example seems to imply that there's some context
   switch: the outer ?depends() works on the "current package" foo,
   while the inner ?version(2\.0) works on the version of foo's dependencies.
   However, that doesn't seem to follow from
   /usr/share/doc/aptitude/html/en/ch02s04s05.html#searchDep


(a) would be more like working with joins/intersections/etc. on (multiple)
sets of (package,tuple).
(b) is more like how some parts of the documentation seem to explain it, but
kinda doesn't really seem to fit.

So I kinda miss the general way of how things are acutally processed - in which
direction and what's actually returned (packages? packages+versions?)

But that seems important for cases like:
?installed ?version(CANDIDATE)
=> when ?installed and ?version returns versions and implicit ?and matches only names, 
   this should yield something different if it also matches version (in which case
   it would, I guess, only match packages whose installed version equals the candidate
   version?



There seem to be quite some ambiguities
E.g. it says:
- "By default, a pattern matches a package if any version of the package matches the pattern."
  => sounds as if it would be only about the package name (not the version)
  and
  "For instance, the search term ?depends(pattern) will select any package that depends on a
   package matching pattern. However, pattern will only be checked against the versions of
  the package that actually satisfy a dependency."
  => That again sounds, as if the patterns would be evaluated from outer terms to inner terms.
  => What does a term actually "return"? Is it just the name of the package or is it one or
     many (package,version) tuples?

Or:
- "There is a subtle, but important, distinction between matching a pattern against a package,
   and matching it against all the versions of that package. When a pattern is matched against
   a package, each of its terms is matched against the package, and so each term will match if
   any version of the package matches."
  => The whole paragraph is rather difficult to understand.
     Seems to imply, that there are two kinds of patterns, one matching names the other
     matching (name,verson).
     Also I guess the crucial point is missing, namely that in the former case, the different
     (sub) terms of a pattern need not match against the same (of any) version?
but:
- the description of ?any-version(pattern) says:
  "To be precise, as with any other pattern, it is not packages but versions of the packages which
   are matched."
  => rather implyin that all terms woul be handled the same ann always match versions


Or:
The description of ?any-version(pattern) again:
"Matches a package if any one of its versions matches the enclosed pattern."
AFAIU, the real point here is, that it matches if the pattern (i.e. all sub-patterns) matches,
if all of them match against *the same version* of at least one of all the package's versions.


For ?archive() and ?origin, it would be nice if this would perhaps remind people, that
obsolete packages are obviously never matched.
Perhaps even, that archive is the same thing as "suite"?


Perhaps clarify, whether ?installed is exactly the same as ?version(CURRENT)?


IIRC, there were examples using things like this ?archive(testing), which is however dangerous,
as peoeple will adapt that to write ?archive(stable), which does however include unstable as well,
doesn't it?
I think all such patterns (also ?origin) should be rewritten like ^testing$



When ~narrow(pat1, pat2) is identical to ?any-version(pat1 pat2), is there any difference
between ?any-version(pat1 pat2 pat3) and ~narrow(pat1 pat3, pat2) or ~narrow(pat1, pat2 pat3)?


Does the "narrowed" context of ~narrow(pat1, pat2) only affect when matching pat1 with pat2
ot does it inherit down, e.g. consider:
aptitude search '?narrow(?installed, ?not( ?archive("^stable$") ))'
=> "easy"... AFAIU... the ?installed selects any (package,version) that is installed, and the
   intersects it with any (package,version) that is not in stable.

aptitude search '?narrow(?installed, ?not( ?archive("^stable$")  ?archive("^testing$") ))'
=> if the narrowed context goes down inside the ?not, then ?archive("^stable$")  ?archive("^testing$")
   should be empty, I guess, unless there are same versions in both stable and testing
   if it doesn't go down, then ?archive("^stable$")  ?archive("^testing$") should, AFAIU, yield
   all packages which have *any* (same/different) version in both, stable and testing.





5) Useful examples
I think it would be nice if the documentation gives useful examples.

Packages where the installed version comes from a certain origin:
  ?narrow( ?installed, ?origin("^Debian Backports$") )
with several possible origins:
  ?narrow( ?installed, ?origin("^(Debian Backports|My Local Organisation)$") )
  which I guess is effectively the same than:
  ?narrow( ?installed, ?origin("^Debian Backports$") | ?origin("^My Local Organisation$") )
  the former workgin with regex alternatives the later with pattern alternatives

=> these won't include obsolet packages, I guess


Packages where the installed version *does not* come from some origin (typically to
search for packages not from Debian):
  ?narrow( ?installed, !?origin("^Debian$") )
with several allowed origins:
  ?narrow( ?installed, !?origin("^(Debian|Debian Backports)$") )
  which I guess is effectively the same than:
  ?narrow( ?installed, !( ?origin("^Debian$") | ?origin("^Debian Backports$") ) )

=> these will also include obsolete packages and also packages which are actually (i.e. their
   "newest version) still in Debian, but just not yet upgraded
   so the query is in practise less useful, IMO


Packages where the installed version *does not* come from some suite (typically to
search for packages outside of e.g. stable (and perhaps the corresponding stable-updates
suite):
  ?narrow( ?installed, !?archive("^stable$") )
with several allowed archives:
  ?narrow( ?installed, !?archive("^(stable|stable-updates)$") )
  which I guess is effectively the same than:
  ?narrow( ?installed, !( ?archive("^Debian$") | ?origin("^stable-updates$") ) )

=> these will also include obsolete packages and also packages which are actually (i.e. their
   "newest version) still in Debian, but just not yet upgraded
   so the query is in practise less useful, IMO




So I guess what people really want in practise with the examples above, but using the
candidate instead of the installed version.
E.g. the following doesn't work:
  ?narrow( ?version(CANDIDATE), !?origin("^(Debian|Debian Backports)$") )
as it matches all candidate versions (of all, including not installed, packages).


I guess the following does the job, but I'm not totally sure, given that I don't
fully understand the matching yet:


Packages where the candidate version of installed packages *does not* come from some origin (typically to
search for packages not from Debian):
  ?installed ?narrow( ?version(CANDIDATE), !?origin("^Debian$") )
with several allowed origins:
  ?installed ?narrow( ?version(CANDIDATE), !?origin("^(Debian|Debian Backports)$") )

=> should still include obsolete packages


Packages where the candidate version of installed packages *does not* come from some suite (typically to
search for packages outside of e.g. stable (and perhaps the corresponding stable-updates
suite):
  ?installed ?narrow( ?version(CANDIDATE), !?archive("^stable$") )
with several allowed archives:
  ?installed ?narrow( ?version(CANDIDATE), !?archive("^(stable|stable-updates)$") )

=> should still include obsolete packages


The idea of these is, that the ?narrow(...) matches any candidate version, which are not
in the respecitve origin or suite, which would however include also non-installed packages.
So the "and" with ?installed filters out the later.


One should perhaps also mention, that the above is smart enough (AFAIU) to also select
packages which are e.g. still in some origin, but nevertheless won't get updates anymore:
I found the following case on one of our systems:
# aptitude --disable-columns --display-format '%c%M %p' search '?installed ?narrow( ?version(CANDIDATE), !?origin("^(Debian|Debian Backports)$") )'  |  column -t -s ' 'i
iA  libssl1.0.0

# apt-cache policy libssl1.0.0
libssl1.0.0:
  Installed: 1.0.1t-1+deb8u6
  Candidate: 1.0.1t-1+deb8u6
  Version table:
 *** 1.0.1t-1+deb8u6 100
        100 /var/lib/dpkg/status
     1.0.1t-1+deb7u4 600
         -1 http://security.debian.org/debian-security wheezy/updates/main amd64 Packages
     1.0.1e-2+deb7u20 600
         -1 http://debian.mirror.lrz.de/debian wheezy/main amd64 Packages

So while the package itself is still in some of the selecte origins (the two repos below),
the candidate version is not.
So libssl1.0.0 1.0.1t-1+deb8u6 wouldn't get any updates at this point and can still be considered
"dead".

I guess the same would also work in the archive case,... cause this is probably what admins
are really interested in:
  Do I have any packages for which I wouldn't get any updates anymore?

Not sure whether the examples above solve this also when taking priorities from apt_preferences
into account.


Maybe, for teaching it would be nice, if one could explain what's the difference from
  ?installed ?narrow(            ?version(CANDIDATE),            !?origin("^Debian$") )
to e.g.
             ?narrow( ?installed ?version(CANDIDATE),            !?origin("^Debian$") )
             ?narrow(            ?version(CANDIDATE), ?installed !?origin("^Debian$") )
AFAIU, the later two are identical? But they both would only match packages, where
the installed and candidate version are the same?




Well,... thanks for considering these ideas :-D

Cheers,
Chris.


More information about the Aptitude-devel mailing list