Le 2019-03-20 22:28, Robert-André Mauchin a écrit :
Can you explain in what context would goipaths be used? What's
goipaths are "real" Go package trees: all the packages under a specific
root, except subtrees which are affected to another package tree
So the project example.com/foo/bar
subdir tree, could be split into the following goipath objects
which makes example.com/foo/bar/A
everything under A except
goaltipaths are "fake" package trees, simulated by a symlink to
goipaths exist because Go upstreams suck at defining their package
hierarchy, and will regularly put inside the tree of A project, a
subtree using B project, when B is itself a descendant of A project. The
only way our packages or the Go compiler can deal with this is to
effectively consider the subtree a separate sub project (ideally, a
separate project but that is up to upstream).
goaltipaths exist because Go upstream insists on allocating a different
name to every fork, but it is way too expensive to switch the imports
back and forth between different forks in source code, so everyone ends
up adding a faking layer to pretend the forked name Go upstream insists
on does not exist and the real name is the original project name (the
traditional Go fake method is to copy the original source in a vendor
tree, then modify it while keeping its original name).
The two concepts have direct equivalents in the Go module design Google
did since: nested modules and module replaces. So Google invented the
same packaging wheel as me, at about the same time (arguably, with a
nicer technical implementation, because they could change the behavior
of the go compiler, and declare a break with the past, while I had to
feed it something that looked like a traditional GOPATH, and didn't want
to break existing packages).
From what I tested:
- goipaths will install several import paths into the same devel
- goaltipaths will generate compat-devel packages in care of renames
I don't understand in what use cases goipaths should be used.
Typically, when you have a problematic requires (a cycle-inducing
requires or a requires that pulls in lots of other things) and you are
lucky enough it is only used in specific project subpackages, and most
project dependents do not need those subpackages directly or indirectly,
you affect the goipaths associated with the problem subpackages to a
separate -devel rpm package, to simplify your dependency graph.
And, the macro code lets you affect those in bulk, because some
upstreams are not so nice as to put all the problem bits under a single
I don't recall
ever seeing a Go source package with two import paths at the same time.
so, why would we install both in the same devel package, instead of
package for each import path.
You could certainly create as many devel packages as you have subtrees,
but that gets expensive fast (lots of package descriptions to write,
lots of separate packages for rpm to handle) and it may make no
technical sense (the subtrees are so interlinked they can not be
installed separately). Therefore the macro code compromises and allows
the packager to affect a list of subtrees to the same package as another
It's a packaging option. You don't need to use it. You can take every
goipath in the goipaths list and put it in a separate goipath<number>
variable, that will cause it to be packaged in a separate devel rpm
It's not used within Fedora because trying to do subtree surgery without
tooling is hopelessly dangerous, and Fedora tooling changes, fixes and
enhancements have been blocked for a long time. The existing Fedora
macro code does contain the seed of all this goipath jungling, but it
was not given the possibility to mature and get more polished (the
polishing was done outside Fedora in spring/early summer 2018, at the
time Fedora Go tooling organization finished breaking down).
Like I wrote, while Fedora was deadlocking its Go rpm tooling, Go
upstream reinvented the same concept as nested modules, with most of the
same design decisions.
The need for goaltipaths (and Go Module replaces) is much less evident
One one hand, and short-term, they are incredibly convenient.
On the other hand, they're just putting a fig leaf on the breakage
produced by the Go upstream insistence on renaming everything on fork,
and conflating API (the thing Go code needs) with implementation (the
fork you actually want to use). And you end up with code and packages
that no longer have any clear idea, on what API they're calling.
So, their long-term effects are not nice.
I'm not sure I will allow replaces in my experimental Go module tooling.
If I allow replaces, I will advise against using them big time (the same
way goaltipaths produce compat packages, to make very clear you should
try to avoid using them).