-
Notifications
You must be signed in to change notification settings - Fork 696
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: New local fs index.tar-less repository style to simplify "offline" source-distribution #6359
Comments
phadej
added a commit
to phadej/cabal
that referenced
this issue
Dec 18, 2019
Resolve haskell#6359 `preferred-versions` are left out for now. It shouldn't be difficult to add, but needs work nevertheless. Also change the index cache to use `Distribution.Utils.Structured`, making Binary instances generically derived. Almost as a feature generated 01-index.cache is never updated. If you change the contents of the directory, you have to purge 01-index.cache file yourself.
phadej
added a commit
to phadej/cabal
that referenced
this issue
Dec 19, 2019
Resolve haskell#6359 `preferred-versions` are left out for now. It shouldn't be difficult to add, but needs work nevertheless. Also change the index cache to use `Distribution.Utils.Structured`, making Binary instances generically derived. Almost as a feature generated 01-index.cache is never updated. If you change the contents of the directory, you have to purge 01-index.cache file yourself.
phadej
added a commit
to phadej/cabal
that referenced
this issue
Dec 19, 2019
Resolve haskell#6359 `preferred-versions` are left out for now. It shouldn't be difficult to add, but needs work nevertheless. In addtition - change the index cache to use `Distribution.Utils.Structured`, making Binary instances generically derived. - separate Distribution.Client.HashValue into own module. This allows to use HashValue for hashing the part of localRepoPath (breaks module dependency cycle). Almost as a feature generated 01-index.cache is never updated. If you change the contents of the directory, you have to purge 01-index.cache file yourself.
phadej
added a commit
to phadej/cabal
that referenced
this issue
Dec 20, 2019
Resolve haskell#6359 `preferred-versions` are left out for now. It shouldn't be difficult to add, but needs work nevertheless. In addtition - change the index cache to use `Distribution.Utils.Structured`, making Binary instances generically derived. - separate Distribution.Client.HashValue into own module. This allows to use HashValue for hashing the part of localRepoPath (breaks module dependency cycle). Almost as a feature generated 01-index.cache is never updated. If you change the contents of the directory, you have to purge 01-index.cache file yourself.
phadej
added a commit
to phadej/cabal
that referenced
this issue
Dec 20, 2019
Resolve haskell#6359 `preferred-versions` are left out for now. It shouldn't be difficult to add, but needs work nevertheless. In addtition - change the index cache to use `Distribution.Utils.Structured`, making Binary instances generically derived. - separate Distribution.Client.HashValue into own module. This allows to use HashValue for hashing the part of localRepoPath (breaks module dependency cycle). Almost as a feature generated 01-index.cache is never updated. If you change the contents of the directory, you have to purge 01-index.cache file yourself.
phadej
added a commit
to phadej/cabal
that referenced
this issue
Dec 20, 2019
Resolve haskell#6359 `preferred-versions` are left out for now. It shouldn't be difficult to add, but needs work nevertheless. In addtition - change the index cache to use `Distribution.Utils.Structured`, making Binary instances generically derived. - separate Distribution.Client.HashValue into own module. This allows to use HashValue for hashing the part of localRepoPath (breaks module dependency cycle). Almost as a feature generated 01-index.cache is never updated. If you change the contents of the directory, you have to purge 01-index.cache file yourself.
phadej
added a commit
to phadej/cabal
that referenced
this issue
Dec 22, 2019
Resolve haskell#6359 `preferred-versions` are left out for now. It shouldn't be difficult to add, but needs work nevertheless. We also allow relative paths, which kind of work, if you are careful. In addtition - change the index cache to use `Distribution.Utils.Structured`, making Binary instances generically derived. - separate Distribution.Client.HashValue into own module. This allows to use HashValue for hashing the part of localRepoPath (breaks module dependency cycle). Almost as a feature generated 01-index.cache is never updated. If you change the contents of the directory, you have to purge 01-index.cache file yourself.
phadej
added a commit
to phadej/cabal
that referenced
this issue
Dec 23, 2019
Resolve haskell#6359 `preferred-versions` are left out for now. It shouldn't be difficult to add, but needs work nevertheless. We also allow relative paths, which kind of work, if you are careful. In addtition - change the index cache to use `Distribution.Utils.Structured`, making Binary instances generically derived. - separate Distribution.Client.HashValue into own module. This allows to use HashValue for hashing the part of localRepoPath (breaks module dependency cycle). Almost as a feature generated 01-index.cache is never updated. If you change the contents of the directory, you have to purge 01-index.cache file yourself.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Problem statement
In various situations, there's the desire to provide a self-contained offline buildable source-distribution that (assuming you have a working toolchain installed, i.e.
ghc
+cabal
) doesn't require any network access to build and install a cabal project. This basically requires to include all the dependencies of a project as part of the source-distribution.In fact, I've hacked up some tooling in the past to accomplish this for my own needs at https://github.com/haskell-hvr/cabal-offline but never got around to polish it and release it properly, as I'm not satisfied with the approach yet.
The way
cabal-offline
's approach is supposed to work is basically to start from theplan.json
file which describes what ingredients the cabal solver deemed necessary for the most recently computed build-plan, and collect the respective.tar.gz
files from the local package repo cache (+ any revised.cabal
metadata files from the respective01-index.tar
).Once we have the dependencies'
.tar.gz
and.cabal
files, we need to provide those to cabal's solver. There's basically 3 options here:packages: deps/*.tar.gz
packages: deps/*/*.cabal
hackage-repo-tool
)Neither of these options is ideal, and I'll quickly go through these:
Approach 1: Point to the tarballs via
packages: deps/*.tar.gz
This only works conveniently for the case where
.cabal
metadata required (this can be workarounded by with aallow-newer: *:*
+allow-older: *:*
combined with acabal.plan.freeze
file which needs to pin down all cabal flag choices as allow-newed/older might break those otherwise), andThe former (i.e. (A)) can be workarounded (while harming the property (C) mentioned in the next paragraph by repackaging .tar.gz with their revised .cabal file), but the latter (i.e. (B)) is often a real blocker.
(C) On the bright side, dependencies will be properly shared in the Nix-style store, as their sha256sums will be exactly the same you'd have if you had build your project with the real Hackage remote repo. I.e. no recompilation of dependencies needed when you switch between your offline source-distro build and your normal "development" build which might have access to a larger package repo and the build-plan doesn't change.
Approach 2: Unpack and update the .cabal files, and point cabal to them via
packages: deps/*/*.cabal
This addresses (A) but not (B), but completely sacrifices (C), as the dependencies' artefacts are no longer cacheable in the Nix-style store, but instead are treated as local packages and lack proper sha256 sums.
Approach 3: Construct a file-local package repository (with e.g.
hackage-repo-tool
)This approach nicely addressed (A), (B) while retaining (C). But it's got a few annoyances (which I'll denote as (D)); I'll explain:
So we currently support a number styles of package repositories via the
repository
directive in~/.cabal/config
andcabal.project
files (c.f. https://cabal.readthedocs.io/en/latest/installing-packages.html#repository-specification)remote-repo
denotes)local-repo
)As a side-remark: for the Nix-style build paradigm, the non-TUF repositories are very inconvenient, as they don't provide the tarball sha256sums in their metadata, which the solver phase needs to compute nix-style hashes for the build-plan. This would require the solver to unnecessarily fetch .tar.gzs for the purpose of computing their sha256sums even if they were already cached in the nix-style store and thus we wouldn't have needed to download their source to begin with...
(D) So, one annoyance is that you have to run
hackage-repo-tool
and construct a redundant01-index.tar.gz
from the set of.tar.gz
and revised.cabal
files. In order to do that, you also need to create some dummy TUF secret keys to sign the dummy TUF metadata with, and construct arepository
-directive with the appropriateroot-keys
andkey-threshold
settings in your distribtuedcabal.project
file. Moreover, another annoyance is that the TUF signatures would expire at some point, and then cabal would refuse to build the source-dist...So ultimately I don't think that local TUF-secured repos make much sense for this use-case as they come with accidental complexity, and why would you even want to TUF-signatures in the first place for a source-distribution whose local sources you'd typically sign externally anyway by signing the tar'ed up aggregate deliverable source-distro wholesale?
Proposal
Consequently, I propose to combine the benefits the 3 approaches (i.e. addressing (A)+(B), while achieving (C) and avoiding (D)) by providing a new style of index/TUF-less local package repositories, by introducing a new uri schema
file+noindex:
likefile+noindex:
must point to a folder in the filesystem. The folder/path/to/local/repo/
in the example above (which could also be a relative path such asfile+noindex:./deps/
) would contain files of the form${pkgid}.tar.gz
,${pkgid}.cabal
(optional; a corresponding${pkgid}.tar.gz
must exist!), orpreferred-versions
(optional)Then cabal would scan that folder and compute sha256sums on the fly (which is quite cheap) and construct its package index data-structure (which it could also cache easily).
So the minimal form would be to have the folder contain merely
${pkgid}.tar.gz
files, which would already be able to address (B) in the absence of revised .cabal files; i.e. allow for multiple versions of the same package.If there's also a
${pkgid}.cabal
for a given${pkgid}.tar.gz
, then this.cabal
file is taken as the package description for${pkgid}
. If it's missing, cabal will extract the.cabal
file from the respective${pkgid}.tar.gz
(and ideally cache it).If there's a
preferred-versions
file, then do cabal will treat it as if it was a combinedpreferred-versions
file from theindex-01.tar.gz
(or how it was represented in the legacy00-index.tar.gz
file).This would considerably simplify the implementation of tooling such as
cabal-offline
, maybe to the point where we could even simply integrate it directly intocabal
proper.Possible future work
(NB: this is not part of the proposal proper; this merely loud thinking to express possible directions on how this feature could be leveraged)
...imagine a
cabal sdist --offline
operation; but having this in an companion tool is fine too as I can think of various ways to tweak the offline bundle generation (e.g. take a set of plan.json files for various computed build-plans for different configurations; e.g. for different GHC versions or platforms; and construct an offline source-distro that is able to work on all of these; or have a planjson2bash conversion which is able to emit a bash script for a given plan.json buildplan, and include those in the source-dist -- think cabal'sbootstrap.sh
; there's lots of ideas to explore here, and these might be better to explore in a decoupled tool rather than bloat cabal and add to its maintenance overhead...)The text was updated successfully, but these errors were encountered: