1{ lib, gemConfig, ... }:
2
3let
4 inherit (lib) attrValues concatMap converge filterAttrs getAttrs
5 intersectLists;
6
7in rec {
8 bundlerFiles = {
9 gemfile ? null
10 , lockfile ? null
11 , gemset ? null
12 , gemdir ? null
13 , ...
14 }: {
15 inherit gemdir;
16
17 gemfile =
18 if gemfile == null then assert gemdir != null; gemdir + "/Gemfile"
19 else gemfile;
20
21 lockfile =
22 if lockfile == null then assert gemdir != null; gemdir + "/Gemfile.lock"
23 else lockfile;
24
25 gemset =
26 if gemset == null then assert gemdir != null; gemdir + "/gemset.nix"
27 else gemset;
28 };
29
30 filterGemset = { ruby, groups, ... }: gemset:
31 let
32 platformGems = filterAttrs (_: platformMatches ruby) gemset;
33 directlyMatchingGems = filterAttrs (_: groupMatches groups) platformGems;
34
35 expandDependencies = gems:
36 let
37 depNames = concatMap (gem: gem.dependencies or []) (attrValues gems);
38 deps = getAttrs depNames platformGems;
39 in
40 gems // deps;
41 in
42 converge expandDependencies directlyMatchingGems;
43
44 platformMatches = {rubyEngine, version, ...}: attrs: (
45 !(attrs ? platforms) ||
46 builtins.length attrs.platforms == 0 ||
47 builtins.any (platform:
48 platform.engine == rubyEngine &&
49 (!(platform ? version) || platform.version == version.majMin)
50 ) attrs.platforms
51 );
52
53 groupMatches = groups: attrs:
54 groups == null || !(attrs ? groups) ||
55 (intersectLists (groups ++ [ "default" ]) attrs.groups) != [];
56
57 applyGemConfigs = attrs:
58 (if gemConfig ? ${attrs.gemName}
59 then attrs // gemConfig.${attrs.gemName} attrs
60 else attrs);
61
62 genStubsScript = { lib, ruby, confFiles, bundler, groups, binPaths, ... }: ''
63 ${ruby}/bin/ruby ${./gen-bin-stubs.rb} \
64 "${ruby}/bin/ruby" \
65 "${confFiles}/Gemfile" \
66 "$out/${ruby.gemPath}" \
67 "${bundler}/${ruby.gemPath}/gems/bundler-${bundler.version}" \
68 ${lib.escapeShellArg binPaths} \
69 ${lib.escapeShellArg groups}
70 '';
71
72 pathDerivation = { gemName, version, path, ... }:
73 let
74 res = {
75 type = "derivation";
76 bundledByPath = true;
77 name = gemName;
78 version = version;
79 outPath = "${path}";
80 outputs = [ "out" ];
81 out = res;
82 outputName = "out";
83 };
84 in res;
85
86 composeGemAttrs = ruby: gems: name: attrs: ((removeAttrs attrs ["platforms"]) // {
87 inherit ruby;
88 inherit (attrs.source) type;
89 source = removeAttrs attrs.source ["type"];
90 gemName = name;
91 gemPath = map (gemName: gems.${gemName}) (attrs.dependencies or []);
92 });
93}