Subject: [bug#68163] [PATCH] gnu: Prevent stale cache use when `%package-module-path' is parameterized.

From: antlers <[email-masked]>
Date: Fri, 12 Jan 2024 16:23:30 -0800

> ’fold-packages’ accepts a list of modules as argument and it
> would be the way you should go

Thanks for the suggestion! I was so focused on making `specification->package'
cooperate, I failed to consider calling `fold-packages' directly; `#:modules'
is exactly the argument I was looking for. I've given it a spin and, while I
have some notes, it works great.

I still think it's worth considering whether the behavior of
`find-packages-by-name/direct' and it's closure in regards to the
parameterization of `%package-module-path' is intentional. A user's intuition
ought to be that dynamically binding a parameter will have the desired and
expected effect, down to the bottom of the call-stack, and
`find-packages-by-name/direct' is arguably presented as the implementation
"under" the caching layer. I'm not sure when it's internal cache is
instantiated, and find this behavior surprising.

Returning to `fold-packages' there are two differences of note, each stemming
from how `:guix' approximates guix's standard command-line format by
appropriating the existing modules.

1.) 

> I guess [...], right?

> If yes, [...] filter based on package name (and/or other information tracked
> under use-package keyword :guix).

Right! And, almost! Package specifications do not always match the
`package-name' field of the package they resolve to. Consider `package+output'
specifications like the venerable `gcc:lib' (RIP), and package aliases like
`gnupg-1', `linux-libre-lts', or `texinfo-7'. This is solve-able (maybe with
`package-name->name+version'), but it's neither as simple as filtering on
`package-name' nor as elegant as re-using the existing modules-- should they
behave appropriately under parameterization.

2)

I can avoid using `specification->package' directly, but would also need to
special-case `options->transformation' when the second argument to
`--with-graft` is such a specification because, unlike the other
transformations, it resolves that via `package->specification' before returning
a procedure (uhm, were I in need of such a transformation). Another solvable
problem, but also another example of an entry-point that could just
`do-what-I-mean' under parameterization-- and there are likely more.

Why rebuild two spokes when, with a small and deliberate tweak, the old wheel
could cooperate with an existing mechanism for exactly this sort of re-tooling?

---

I feel like that's a great place to leave off, but I appreciate your questions
and will take a bit more time answer the rest. 

>  i)  Could you provide some details about the tree of your channel?

Just that it's some custom packages, a home-env with local-files, and some
dubious programming, all in one channel. If the packages were in a separate
channel, or the home-env was kept outside of the repo and provided on the
command-line, everything would work just fine. The rest should be clear from my
elaborations.

> When you run “guix pull”, it builds the Guix channel and all the other
> custom channels, therefore all the packages should be visible from
> ’specification->package’.  Aren’t they?

>  ii) Could you explain when it fails exactly and running which Guix
>      command-line?

I have a typo in my original message:

> this is a compile-time error, so _profiles_ containing such code fail to build

It's *channels*, not profiles (and with the notable exception of guix itself),
that fail to compile when attempting to resolve specifications for packages
they define. We fail before Guix builds the package cache. It might help stage
this in a gexp, but `home-profile-service-type' takes a list (not a gexp) and
I'm not sure (yet) how to write the service I need or how that would effect
whether / when it fails. If I knew the package cache better I might know when /
what's missing it (aside from myself) and `force'-ing the cache in the closure
before I get there.

Oh my, time does fly!
Thanks again for the questions, and the help. I really could roll with
`fold-packages', but I'd rather keep the patch than build any more spokes. I
think the behavior is cleaner and I hope I've made a good case for that,
regardless of whether I'd recommend use-cases indulging in dynamic binding--
the parameter already exists and should treated as a volatile value.