-
Notifications
You must be signed in to change notification settings - Fork 24
WIP: Better packages
detection
#93
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
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# Like pkgs.haskell.lib.haskellPathsInDir' but with a few differences | ||
# - Allows top-level .cabal files | ||
# - Recurses into subdirectories | ||
# - Allows package.yaml files | ||
{ lib, ... }: | ||
|
||
path': | ||
|
||
let | ||
parseCabalName = file: | ||
lib.strings.removeSuffix ".cabal" file; | ||
parseHpackName = file: | ||
# TODO: this is a hack, we should use a proper parser | ||
let | ||
line = builtins.head (lib.strings.split "[[:space:]]*\n[[:space:]]*" (builtins.readFile file)); | ||
extract = xs: builtins.head (builtins.tail (builtins.tail xs)); | ||
in | ||
extract (lib.strings.split "[[:space:]]*name[[:space:]]*:[[:space:]]*" line); | ||
f = path: lib.mapAttrsToList | ||
(k: v: | ||
let | ||
pass = [ ]; | ||
one = x: [ x ]; | ||
in | ||
if v == "regular" | ||
then | ||
if lib.strings.hasSuffix ".cabal" k | ||
then one (lib.nameValuePair (parseCabalName k) path) | ||
else if k == "package.yaml" | ||
then one (lib.nameValuePair (parseHpackName k) path) | ||
else pass | ||
else | ||
if v == "directory" | ||
then | ||
if builtins.pathExists (path + "/${k}/${k}.cabal") | ||
then | ||
one (lib.nameValuePair k (path + "/${k}")) | ||
else | ||
if builtins.pathExists (path + "/${k}/package.yaml") | ||
then one (lib.nameValuePair (parseHpackName (path + "/${k}/package.yaml")) (path + "/${k}")) | ||
else f (path + "/${k}") | ||
else pass | ||
) | ||
(builtins.readDir path); | ||
in | ||
lib.listToAttrs (lib.flatten (f path')) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Recursing into arbitrary subdirectories hurts performance. This will be exacerbated by projects that rely on lazy fetching of git submodules.
Not sure if perfect exists. I'd prefer a cabal.project or stack.yaml parser.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't nix copy the source tree to the store anyway? I ran this on a large internal mono repo with 31 packages using package.yaml which all lie as far as 5 sub-directories deep, and didn't notice a perceptible difference (to be fair, this was on my M1 Max). But yes performance degradation is a valid concern. I'll benchmark it properly before we stamp this PR for approval.
Lazy fetching of git submodules?
I don't know about stack (why would someone use stack if there is Nix?) - but
cabal.project
parsing is indeed better (ie. #76); here's ourcabal.project
(
cabal.project
doesn't support hpack, so we would also have to look forpackage.yaml
)I suppose we can just write a Haskell executable (put it in
pkgs.haskellPackages.<whatever>
) and then use that to get a JSON back. This Haskell executable can also expose the hpack YAML data as JSON to Nix. In a way, it would be like cabal2nix. Maybe I should just go this route instead of this PR ...There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like https://github.com/NorfairKing/cabal2json#readme
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This Haskell executable can even do the traversal and return packages information.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I should have explained myself. I'm considering unimplemented lazy-trees features.
The
stack repl
multi-module hack is rather useful. You can load a repl where all local packages are quick-reloadable.There's also horizon-haskell, which is like Nixpkgs Haskell, but more stackage based.
It would be really nice to avoid IFD for this purpose. Ideally, the set of flake attribute names can be determined without doing any IFD. This keeps evaluation quick, especially on monorepos, and especially when you don't always need a haskell package in an evaluation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nix flake show --option allow-import-from-derivation false
#95