Get "<category>/<port>" from "<port>-<version>", including for things that are not installed?

If I have something of the form "<port>-<version>", is there a reliable way to determine the corresponding "<category>/<port>"? For example, given pkg-1.19.1_1, I'd like to get ports-mgmt/pkg.

Importantly, I'd like to be able to do this regardless of whether the port/package is installed, so (I think?) pkg info doesn't answer the question.

It can be assumed that the only "<port>-<version>" strings that will be used as input are things that actually could be built given the current state of /usr/ports and whatnot. In fact, even beyond that, I don't really care about "<version>" at all (unless it is somehow actually needed in order to determine "<category>/<port>". That is, for example, I'd want any of pkg-1.2.1, pkg-1.19.1_1, and pkg-438.65.92_234 to all resolve to ports-mgmt/pkg.

I also don't need flavors taken into account. For example, it will never be asked to resolve py-setuptools@py39-63.1.0 (or whatever the format is); it would instead be asked to resolve py39-setuptools-63.1.0.

It seems easy to get something that will often work, by doing something like getting pkg from pkg-1.19.1_1 and then scanning /usr/ports/ for directories of the form "<category>/pkg/", but there are several problems (or at least potential problems, given my ignorance) with this:
  • Port names can contain hyphens, numbers, and periods, and I'm not sure that versions cannot contain (say) hyphens. Is it definitely the case that the very last hyphen is what separates <port> from <version>?
  • A port can be in more than one category. Is there a concept of a "canonical" category for a port, and if so, can it be algorithmically determined which category that is? I notice that although (e.g.) python39 is in both lang and python, there is no /usr/ports/python/ directory. However, I don't know that it is always the case that a port cannot be in more than one category having a corresponding /usr/ports/ subdirectory.
  • Similar potential issue: Is it possible for two entirely different ports to have the same port name (in different categories)? For example, deli/submarine and navy/submarine?
  • Is it even necessarily the case that the "<port>" in "<port>-<version>" is the same as the "<port>" in the "<category>/<port>" subdirectory of /usr/ports that would be used to build it in the first place?
Thanks.
 
Also, I want to be clear that I am not wed to this idea of mine:
It seems easy to get something that will often work, by doing something like getting pkg from pkg-1.19.1_1 and then scanning /usr/ports/ for directories of the form "<category>/pkg/"
In fact, I'd prefer a different way, as scanning /usr/ports could take quite a while if not cached.
 
  • package versions can't contain hyphens
  • every port only has ONE primary category, and this must be a "physical" category (IOW, a directory for it exists in the tree). It's only located there in the tree
  • port and package names must be unique
  • package names can differ from port names, typically by adding prefixes or suffixes which is often used by flavors
That all said, what actual problem do you want to solve that way? :-/
 
That all said, what actual problem do you want to solve that way? :-/

I don't think it's really a problem, but:

I use ports-mgmt/synth to handle my ports management, and for various reasons I want a way to determine why it built something. It's not necessarily the case that the thing that was built will actually be installed (which is why I think pkg info doesn't necessarily help).

For every particular thing it builds, Synth creates a specific log file, named "<category>___<port>[@<flavor>].pkg". In its specific log file relating to the building of a particular package <x>, it will (seemingly) always put out a line of the form "Installing existing package /packages/All/<port>-<version>.pkg" for all packages that <x> needs. In the past, when I've wanted to determine something like this, I've just grepped all the log files for such a string related to the port I'm looking for.

That's generally been fine, but I'd prefer to have a couple little scripts that I could use to do it (and the other direction too), and earlier today I decided to make them. But it soon became clear that although my plan (outlined in the original post) would often work, I didn't know that it would necessarily work.
 
P=tidy-lib; sqlite3 /var/db/pkg/repo-FreeBSD.sqlite "select p.name,p.origin,group_concat(c.name) from packages as p, categories as c,pkg_categories as pc where p.id=pc.package_id and c.id = pc.category_id and p.name='$P' group by p.id order by p.name;"
 
P=tidy-lib; sqlite3 /var/db/pkg/repo-FreeBSD.sqlite "select p.name,p.origin,group_concat(c.name) from packages as p, categories as c,pkg_categories as pc where p.id=pc.package_id and c.id = pc.category_id and p.name='$P' group by p.id order by p.name;"
Thanks so much - this DB looks very helpful not only for this particular question of mine, but also for other things I'd like to do.

When is this DB brought up to date? I'm guessing maybe by portsnap update?
 
For the benefit of anyone finding this thread in the future: There is (at least for me) also repo-Synth.sqlite, which I presume Synth uses rather than repo-FreeBSD.sqlite. It seems (again, for me at least) more up-to-date (in terms of versions), but less complete (in terms of ports). For example:

Code:
# sqlite3 /var/db/pkg/repo-Synth.sqlite
SQLite version 3.41.0 2023-02-21 18:09:37
Enter ".help" for usage hints.
sqlite> select origin, name, version from packages where name like '%rust%' order by origin asc, name asc;
lang/rust|rust|1.68.2
Code:
# sqlite3 /var/db/pkg/repo-FreeBSD.sqlite
SQLite version 3.41.0 2023-02-21 18:09:37
Enter ".help" for usage hints.
sqlite> select origin, name, version from packages where name like '%rust%' order by origin asc, name asc;
comms/trustedqsl|trustedqsl|2.6.3
devel/p5-Pod-Coverage-TrustPod|p5-Pod-Coverage-TrustPod|0.100006
(... many others...)
lang/rust|rust|1.67.1
(... many OTHER others...)

So (apparently) these DBs are not necessarily useful in some situations, but the Synth one seems useful at least for the specific purpose I originally asked about in this thread.
 
Back
Top