on iko/ghcjs-patch-master help sign in
Use new cleanSourceWith to filter component source (#209)
0366537Hamish Mackenzie
builder/comp-builder.nix+9−2
@@ -43,6 +43,11 @@
43}:
43}:
44
44
45let
45let
46+ # TODO fix cabal wildcard support so hpack wildcards can be mapped to cabal wildcards
47+ cleanSrc = if cabal-generator == "hpack" && !(package.cleanHpack or false)
48+ then builtins.trace ("Cleaning component source not supported for hpack package: " + name) src
49+ else haskellLib.cleanCabalComponent package component src;
50+
46 fullName = if haskellLib.isAll componentId
51 fullName = if haskellLib.isAll componentId
47 then "${name}-all"
52 then "${name}-all"
48 else "${name}-${componentId.ctype}-${componentId.cname}";
53 else "${name}-${componentId.ctype}-${componentId.cname}";
@@ -116,12 +121,14 @@ in stdenv.lib.fix (drv:
116stdenv.mkDerivation ({
121stdenv.mkDerivation ({
117 name = fullName;
122 name = fullName;
118
123
124+ src = cleanSrc;
125+
119− inherit src doCheck doCrossCheck dontPatchELF dontStrip;
126+ inherit doCheck doCrossCheck dontPatchELF dontStrip;
120
127
121 passthru = {
128 passthru = {
122 inherit (package) identifier;
129 inherit (package) identifier;
123 config = component;
130 config = component;
124− inherit configFiles executableToolDepends;
131+ inherit configFiles executableToolDepends cleanSrc;
125 env = shellWrappers;
132 env = shellWrappers;
126
133
127 # The directory containing the haddock documentation.
134 # The directory containing the haddock documentation.
builder/setup-builder.nix+29−9
@@ -3,28 +3,48 @@
3{ setup-depends, package, name, src, flags }:
3{ setup-depends, package, name, src, flags }:
4
4
5let
5let
6+ component = {
7+ depends = setup-depends;
8+ libs = [];
9+ frameworks = [];
10+ doExactConfig = false;
11+ # We have to set hsSourceDirs or cleanCabalComponent will
12+ # include everything (and as a result all the components of
13+ # the package will depend on eveything in the package).
14+ # TODO find a better way
15+ hsSourceDirs = ["setup-src"];
16+ includeDirs = [];
17+ asmSources = [];
18+ cSources = [];
19+ cmmSources = [];
20+ cxxSources = [];
21+ jsSources = [];
22+ extraSrcFiles = [ "Setup.hs" "Setup.lhs" ];
23+ };
24+ cleanSrc = haskellLib.cleanCabalComponent package component src;
25+
6 fullName = "${name}-setup";
26 fullName = "${name}-setup";
7
27
8 includeGhcPackage = lib.any (p: p.identifier.name == "ghc") setup-depends;
28 includeGhcPackage = lib.any (p: p.identifier.name == "ghc") setup-depends;
9
29
10 configFiles = makeSetupConfigFiles {
30 configFiles = makeSetupConfigFiles {
11 inherit (package) identifier;
31 inherit (package) identifier;
12− inherit fullName flags;
32+ inherit fullName flags component;
13− component = {
14− depends = setup-depends;
15− libs = [];
16− frameworks = [];
17− doExactConfig = false;
18− };
19− };
33+ };
20
34
21in
35in
22 stdenv.lib.fix (drv:
36 stdenv.lib.fix (drv:
23 stdenv.mkDerivation {
37 stdenv.mkDerivation {
24 name = "${fullName}";
38 name = "${fullName}";
25− inherit src;
39+ src = cleanSrc;
26 nativeBuildInputs = [ghc];
40 nativeBuildInputs = [ghc];
27
41
42+ passthru = {
43+ inherit (package) identifier;
44+ config = component;
45+ inherit configFiles cleanSrc;
46+ };
47+
28 CABAL_CONFIG = configFiles + /cabal.config;
48 CABAL_CONFIG = configFiles + /cabal.config;
29 phases = ["unpackPhase" "buildPhase" "installPhase"];
49 phases = ["unpackPhase" "buildPhase" "installPhase"];
30 buildPhase = ''
50 buildPhase = ''
default.nix+12−6
@@ -178,12 +178,13 @@ let
178
178
179 mkLocalHackageRepo = import ./mk-local-hackage-repo { inherit (self) hackageTarball; inherit pkgs; };
179 mkLocalHackageRepo = import ./mk-local-hackage-repo { inherit (self) hackageTarball; inherit pkgs; };
180
180
181− dotCabal = { index-state, sha256 }@args:
181+ dotCabal = { index-state, sha256, cabal-install ? pkgs.cabal-install }@args:
182− pkgs.runCommand "dot-cabal-at-${builtins.replaceStrings [":"] [""] index-state}" { nativeBuildInputs = [ pkgs.cabal-install ]; } ''
182+ pkgs.runCommand "dot-cabal-at-${builtins.replaceStrings [":"] [""] index-state}" { nativeBuildInputs = [ cabal-install ]; } ''
183 mkdir -p $out/.cabal
183 mkdir -p $out/.cabal
184 cat <<EOF > $out/.cabal/config
184 cat <<EOF > $out/.cabal/config
185 repository cached
185 repository cached
186− url: file:${self.mkLocalHackageRepo args}
186+ url: file:${self.mkLocalHackageRepo
187+ (builtins.removeAttrs args ["cabal-install"])}
187 secure: True
188 secure: True
188 root-keys:
189 root-keys:
189 key-threshold: 0
190 key-threshold: 0
@@ -205,13 +206,18 @@ let
205 # Resulting nix files are added to nix-plan subdirectory.
206 # Resulting nix files are added to nix-plan subdirectory.
206 callCabalProjectToNix = import ./lib/call-cabal-project-to-nix.nix {
207 callCabalProjectToNix = import ./lib/call-cabal-project-to-nix.nix {
207 index-state-hashes = import indexStateHashesPath;
208 index-state-hashes = import indexStateHashesPath;
208− inherit (buildPackages) dotCabal;
209+ inherit (buildPackages) dotCabal haskellLib;
209− pkgs = buildPackages.pkgs; # buildPackages;
210+ pkgs = buildPackages.pkgs;
210 inherit (buildPackages.pkgs.haskellPackages) hpack;
211 inherit (buildPackages.pkgs.haskellPackages) hpack;
211 inherit (buildPackages.pkgs) runCommand cabal-install ghc symlinkJoin cacert;
212 inherit (buildPackages.pkgs) runCommand cabal-install ghc symlinkJoin cacert;
212 inherit (buildPackages) nix-tools;
213 inherit (buildPackages) nix-tools;
213 };
214 };
214
215
216+ # Loads a plan and filters the package directories using cleanSourceWith
217+ importAndFilterProject = import ./lib/import-and-filter-project.nix {
218+ inherit pkgs haskellLib;
219+ };
220+
215 # References to the unpacked sources, for caching in a Hydra jobset.
221 # References to the unpacked sources, for caching in a Hydra jobset.
216 source-pins = self.callPackage ./lib/make-source-pins.nix {
222 source-pins = self.callPackage ./lib/make-source-pins.nix {
217 sources = [ hackageSrc stackageSrc pkgs.path ];
223 sources = [ hackageSrc stackageSrc pkgs.path ];
@@ -238,7 +244,7 @@ let
238 tar xzf ${tarball}
244 tar xzf ${tarball}
239 mv "${name}-${version}" $out
245 mv "${name}-${version}" $out
240 '';
246 '';
241− in let plan-pkgs = import (callCabalProjectToNix { inherit src; index-state = builtins.trace "Using index-state: ${index-state}" index-state; });
247+ in let plan-pkgs = (callCabalProjectToNix { inherit src; index-state = builtins.trace "Using index-state: ${index-state}" index-state; }).pkgs;
242 in let pkg-set = mkCabalProjectPkgSet { inherit plan-pkgs; };
248 in let pkg-set = mkCabalProjectPkgSet { inherit plan-pkgs; };
243 in pkg-set.config.hsPkgs.${name};
249 in pkg-set.config.hsPkgs.${name};
244 });
250 });
docs/reference/library.md+41
@@ -177,8 +177,49 @@ A derivation containing the `nix-tools` [command-line tools](commands.md).
177
177
178## callStackToNix
178## callStackToNix
179
179
180+Runs `stack-to-nix` and produces the output needed for
181+`importAndFilterProject`.
182+
183+**Example**:
184+
185+```nix
186+ pkgSet = mkStackPkgSet {
187+ stack-pkgs = (importAndFilterProject (callStackToNix {
188+ src = ./.;
189+ })).pkgs;
190+ pkg-def-extras = [];
191+ modules = [];
192+ };
193+```
194+
195+
180## callCabalProjectToNix
196## callCabalProjectToNix
181
197
198+Runs `cabal new-configure` and `plan-to-nix` and produces the output
199+needed for `importAndFilterProject`.
200+
201+**Example**:
202+
203+```nix
204+ pkgSet = mkCabalProjectPkgSet {
205+ plan-pkgs = (importAndFilterProject (callCabalProjectToNix {
206+ index-state = "2019-04-30T00:00:00Z";
207+ src = ./.;
208+ })).pkgs;
209+```
210+
211+## importAndFilterProject
212+
213+Imports from a derivation created by `callStackToNix`
214+or `callCabalProjectToNix`.
215+
216+The result is an attrset with the following values:
217+
218+| Attribute | Type | Description |
219+|----------------|------|-----------------------------------------------------|
220+| `pkgs` | attrset | that can be passed to `mkStackPkgSet` (as `stack-pkgs`) or `mkCabalProjectPkgSet` (as `plan-pkgs`). |
221+| `nix` | | this can be built and cached so that the amount built in the evaluation phase is not too great (helps to avoid timeouts on Hydra). |
222+
182## hackage
223## hackage
183## stackage
224## stackage
184
225
lib/call-cabal-project-to-nix.nix+11−46
@@ -1,4 +1,4 @@
1−{ dotCabal, pkgs, runCommand, nix-tools, cabal-install, ghc, hpack, symlinkJoin, cacert, index-state-hashes }:
1+{ dotCabal, pkgs, runCommand, nix-tools, cabal-install, ghc, hpack, symlinkJoin, cacert, index-state-hashes, haskellLib }:
2let defaultGhc = ghc;
2let defaultGhc = ghc;
3 defaultCabalInstall = cabal-install;
3 defaultCabalInstall = cabal-install;
4in { index-state ? null, index-sha256 ? null, src, ghc ? defaultGhc,
4in { index-state ? null, index-sha256 ? null, src, ghc ? defaultGhc,
@@ -10,19 +10,19 @@ assert (if (builtins.compareVersions cabal-install.version "2.4.0.0") < 0
10 else true);
10 else true);
11let
11let
12 maybeCleanedSource =
12 maybeCleanedSource =
13− if pkgs.lib.canCleanSource src
13+ if haskellLib.canCleanSource src
14− then pkgs.lib.cleanSourceWith {
14+ then haskellLib.cleanSourceWith {
15 inherit src;
15 inherit src;
16 filter = path: type:
16 filter = path: type:
17 type == "directory" ||
17 type == "directory" ||
18 pkgs.lib.any (i: (pkgs.lib.hasSuffix i path)) [ ".project" ".cabal" "package.yaml" ]; }
18 pkgs.lib.any (i: (pkgs.lib.hasSuffix i path)) [ ".project" ".cabal" "package.yaml" ]; }
19 else src;
19 else src;
20
20
21− # Using origSrc bypasses any cleanSourceWith so that it will work when
21+ # Using origSrcSubDir bypasses any cleanSourceWith so that it will work when
22 # access to the store is restricted. If origSrc was already in the store
22 # access to the store is restricted. If origSrc was already in the store
23 # you can pass the project in as a string.
23 # you can pass the project in as a string.
24 rawCabalProject =
24 rawCabalProject =
25− let origSrcDir = maybeCleanedSource.origSrc or maybeCleanedSource;
25+ let origSrcDir = maybeCleanedSource.origSrcSubDir or maybeCleanedSource;
26 in if cabalProject != null
26 in if cabalProject != null
27 then cabalProject
27 then cabalProject
28 else
28 else
@@ -81,7 +81,7 @@ let
81 parseBlock = block:
81 parseBlock = block:
82 let
82 let
83 x = span (pkgs.lib.strings.hasPrefix " ") (pkgs.lib.splitString "\n" block);
83 x = span (pkgs.lib.strings.hasPrefix " ") (pkgs.lib.splitString "\n" block);
84− attrs = parseBlockLines x.fst;
84+ attrs = parseBlockLines x.fst;
85 in
85 in
86 if attrs."--sha256" or "" == ""
86 if attrs."--sha256" or "" == ""
87 then {
87 then {
@@ -137,7 +137,7 @@ let
137 }
137 }
138 else replaceSoureRepos rawCabalProject;
138 else replaceSoureRepos rawCabalProject;
139
139
140− plan = runCommand "plan-to-nix-pkgs" {
140+ plan-nix = runCommand "plan-to-nix-pkgs" {
141 nativeBuildInputs = [ nix-tools ghc hpack cabal-install pkgs.rsync pkgs.git ];
141 nativeBuildInputs = [ nix-tools ghc hpack cabal-install pkgs.rsync pkgs.git ];
142 } (''
142 } (''
143 tmp=$(mktemp -d)
143 tmp=$(mktemp -d)
@@ -154,7 +154,8 @@ let
154 export GIT_SSL_CAINFO=${cacert}/etc/ssl/certs/ca-bundle.crt
154 export GIT_SSL_CAINFO=${cacert}/etc/ssl/certs/ca-bundle.crt
155 HOME=${dotCabal {
155 HOME=${dotCabal {
156 index-state = index-state-found;
156 index-state = index-state-found;
157− sha256 = index-sha256-found; }} cabal new-configure \
157+ sha256 = index-sha256-found;
158+ inherit cabal-install; }} cabal new-configure \
158 --with-ghc=${ghc.targetPrefix}ghc \
159 --with-ghc=${ghc.targetPrefix}ghc \
159 --with-ghc-pkg=${ghc.targetPrefix}ghc-pkg
160 --with-ghc-pkg=${ghc.targetPrefix}ghc-pkg
160
161
@@ -179,45 +180,9 @@ let
179
180
180 # run `plan-to-nix` in $out. This should produce files right there with the
181 # run `plan-to-nix` in $out. This should produce files right there with the
181 # proper relative paths.
182 # proper relative paths.
182− (cd $out && plan-to-nix --plan-json $tmp/dist-newstyle/cache/plan.json -o .)
183+ (cd $out && plan-to-nix --full --plan-json $tmp/dist-newstyle/cache/plan.json -o .)
183
184
184 # move pkgs.nix to default.nix ensure we can just nix `import` the result.
185 # move pkgs.nix to default.nix ensure we can just nix `import` the result.
185 mv $out/pkgs.nix $out/default.nix
186 mv $out/pkgs.nix $out/default.nix
186 '');
187 '');
187−in
188+in { projectNix = plan-nix; inherit src; inherit (fixedProject) sourceRepos; }
188− # TODO: We really want this (symlinks) instead of copying the source over each and
189− # every time. However this will not work with sandboxed builds. They won't
190− # have access to `plan` or `src` paths. So while they will see all the
191− # links, they won't be able to read any of them.
192− #
193− # We should be able to fix this if we propagaed the build inputs properly.
194− # As we are `import`ing the produced nix-path here, we seem to be losing the
195− # dependencies though.
196− #
197− # I guess the end-result is that ifd's don't work well with symlinks.
198− #
199− # symlinkJoin {
200− # name = "plan-and-src";
201− # # todo: should we clean `src` to drop any .git, .nix, ... other irelevant files?
202− # buildInputs = [ plan src ];
203− # }
204− runCommand "plan-to-nix-pkgs-with-src" { nativeBuildInputs = [ pkgs.rsync ]; } (''
205− mkdir $out
206− # todo: should we clean `src` to drop any .git, .nix, ... other irelevant files?
207− rsync -a "${src}/" "$out/"
208− rsync -a ${plan}/ $out/
209− '' +
210− ( pkgs.lib.strings.concatStrings (
211− pkgs.lib.lists.zipListsWith (n: f: ''
212− mkdir -p $out/.source-repository-packages/${builtins.toString n}
213− rsync -a "${f}/" "$out/.source-repository-packages/${builtins.toString n}/"
214− '')
215− (pkgs.lib.lists.range 0 ((builtins.length fixedProject.sourceRepos) - 1))
216− fixedProject.sourceRepos
217− )
218− ) + ''
219− # Rsync will have made $out read only and that can cause problems when
220− # nix sandboxing is enabled (since it can prevent nix from moving the directory
221− # out of the chroot sandbox).
222− chmod +w $out
223− '')
lib/call-stack-to-nix.nix+2−11
@@ -9,6 +9,7 @@
9{ src, stackYaml ? null, ignorePackageYaml ? false }:
9{ src, stackYaml ? null, ignorePackageYaml ? false }:
10let
10let
11 stackToNixArgs = builtins.concatStringsSep " " [
11 stackToNixArgs = builtins.concatStringsSep " " [
12+ "--full"
12 "--stack-yaml=${src}/${if stackYaml == null then "stack.yaml" else stackYaml}"
13 "--stack-yaml=${src}/${if stackYaml == null then "stack.yaml" else stackYaml}"
13 (if ignorePackageYaml then "--ignore-package-yaml" else "")
14 (if ignorePackageYaml then "--ignore-package-yaml" else "")
14 "-o ."
15 "-o ."
@@ -30,14 +31,4 @@ let
30 # move pkgs.nix to default.nix ensure we can just nix `import` the result.
31 # move pkgs.nix to default.nix ensure we can just nix `import` the result.
31 mv $out/pkgs.nix $out/default.nix
32 mv $out/pkgs.nix $out/default.nix
32 '';
33 '';
33−in
34+in { projectNix = stack; inherit src; sourceRepos = []; }
34−runCommand "stack-to-nix-pkgs-with-src" { nativeBuildInputs = [ pkgs.rsync ]; } ''
35− mkdir $out
36− # todo: should we clean `src` to drop any .git, .nix, ... other irelevant files?
37− rsync -a "${src}/" "$out/"
38− rsync -a ${stack}/ $out/
39− # Rsync will have made $out read only and that can cause problems when
40− # nix sandboxing is enabled (since it can prevent nix from moving the directory
41− # out of the chroot sandbox).
42− chmod +w $out
43−''
lib/clean-cabal-component.nixnew file+85
@@ -0,0 +1,85 @@
1+# Use cleanSourceWith to filter just the files needed for a particular
2+# component of the package
3+{ lib, cleanSourceWith }: package: component: src:
4+let
5+ srcStr' = src.origSrcSubDir or src.origSrc or null;
6+ # Transform
7+ # "." -> ""
8+ # "./." -> ""
9+ # "./xyz" -> "xyz"
10+ normalizeRelativePath = rel:
11+ if rel == "." || rel == "./."
12+ then ""
13+ else lib.strings.removePrefix "./" rel;
14+ # Like normalizeRelativePath but with a trailing / when needed
15+ normalizeRelativeDir = dir:
16+ let p = normalizeRelativePath dir;
17+ in if p == "" then "" else p + "/";
18+in
19+ if srcStr' == null || package.detailLevel != "FullDetails"
20+ then src
21+ else
22+ let
23+ srcStr = toString srcStr';
24+ dataDir = normalizeRelativeDir package.dataDir;
25+ hsSourceDirs = builtins.map normalizeRelativeDir component.hsSourceDirs
26+ ++ (if component.hsSourceDirs == [] then [""] else []);
27+ includeDirs = builtins.map normalizeRelativeDir component.includeDirs;
28+ dirsNeeded = [dataDir]
29+ ++ hsSourceDirs
30+ ++ includeDirs;
31+ fileMatch = dir: list:
32+ let
33+ prefixes = builtins.map (f: dir + f) (
34+ lib.lists.remove null (lib.lists.flatten (
35+ builtins.map (f: builtins.match "([^*]*)[*].*" f) list)));
36+ exactMatches = builtins.map (f: dataDir + f) (
37+ lib.lists.remove null (lib.lists.flatten (
38+ builtins.map (f: builtins.match "([^*]*)" f) list)));
39+ in rPath: lib.any (d: lib.strings.hasPrefix d rPath) prefixes
40+ || lib.any (d: d == rPath) exactMatches;
41+ dataFileMatch = fileMatch dataDir package.dataFiles;
42+ licenseMatch = fileMatch "" package.licenseFiles;
43+ extraSrcMatch = fileMatch "" (
44+ package.extraSrcFiles
45+ ++ component.extraSrcFiles);
46+ extraDocMatch = fileMatch "" package.extraDocFiles;
47+ otherSourceFiles =
48+ component.asmSources
49+ ++ component.cmmSources
50+ ++ component.cSources
51+ ++ component.cxxSources
52+ ++ component.jsSources;
53+ in cleanSourceWith {
54+ inherit src;
55+ filter = path: type:
56+ assert (if !lib.strings.hasPrefix (srcStr + "/") (path + "/")
57+ then throw ("Unexpected path " + path + " (expected something in " + srcStr + "/)")
58+ else true);
59+ let
60+ srcStrLen = lib.strings.stringLength srcStr;
61+ rPath = lib.strings.substring (srcStrLen + 1) (lib.strings.stringLength path - srcStrLen - 1) path;
62+ # This is a handy way to find out why different files are included
63+ # traceReason = reason: v: if v then builtins.trace (rPath + " : " + reason) true else false;
64+ traceReason = reason: v: v;
65+ in
66+ traceReason "directory is needed" (
67+ lib.any (d: lib.strings.hasPrefix (rPath + "/") d) (
68+ dirsNeeded
69+ ++ package.extraSrcFiles
70+ ++ component.extraSrcFiles
71+ ++ package.extraDocFiles
72+ ++ builtins.map (f:
73+ dataDir + (if dataDir == "" then "" else "/") + f) package.dataFiles
74+ ++ otherSourceFiles))
75+ || traceReason "cabal package definition" (lib.strings.hasSuffix ".cabal" rPath)
76+ || traceReason "hpack package defintion" (rPath == "package.yaml")
77+ || traceReason "data file" (lib.strings.hasPrefix dataDir rPath
78+ && dataFileMatch rPath)
79+ || traceReason "haskell source dir" (lib.any (d: lib.strings.hasPrefix d rPath) hsSourceDirs)
80+ || traceReason "include dir" (lib.any (d: lib.strings.hasPrefix d rPath) includeDirs)
81+ || traceReason "license file" (licenseMatch rPath)
82+ || traceReason "extra source file" (extraSrcMatch rPath)
83+ || traceReason "extra doc file" (extraDocMatch rPath)
84+ || traceReason "other source file" (lib.any (f: f == rPath) otherSourceFiles);
85+ }
lib/clean-source-with.nixnew file+41
@@ -0,0 +1,41 @@
1+# This is a replacement for the cleanSourceWith function in nixpkgs
2+# https://github.com/NixOS/nixpkgs/blob/1d9d31a0eb8e8358830528538a391df52f6a075a/lib/sources.nix#L41
3+# It adds a subDir argument in a way that allows descending into a subdirectory
4+# to compose with cleaning the source with a filter.
5+{ lib }: rec {
6+ cleanSourceWith = { filter ? path: type: true, src, subDir ? "" }:
7+ let
8+ subDir' = if subDir == "" then "" else "/" + subDir;
9+ # In case this is mixed with older versions of cleanSourceWith
10+ isFiltered = src ? _isLibCleanSourceWith;
11+ isFilteredEx = src ? _isLibCleanSourceWithEx;
12+ origSrc = if isFiltered || isFilteredEx then src.origSrc else src;
13+ origSubDir = if isFilteredEx then src.origSubDir + subDir' else subDir';
14+ origSrcSubDir = toString origSrc + origSubDir;
15+ parentFilter = if isFiltered || isFilteredEx
16+ then path: type: src.filter path type
17+ else path: type: true;
18+ filter' = path: type:
19+ # Include parent paths based on the parent filter
20+ (lib.strings.hasPrefix (path + "/") (origSrcSubDir + "/")
21+ && parentFilter path type)
22+ # Children only if both filters return true
23+ || (lib.strings.hasPrefix (origSrcSubDir + "/") path
24+ && (filter path type && parentFilter path type));
25+ in {
26+ inherit origSrc origSubDir origSrcSubDir;
27+ filter = filter';
28+ outPath = (builtins.filterSource filter' origSrc) + origSubDir;
29+ _isLibCleanSourceWithEx = true;
30+ # It is only safe for older cleanSourceWith to filter this one
31+ # if the we are still looking at the root of origSrc
32+ _isLibCleanSourceWith = origSubDir == "";
33+ };
34+
35+ pathHasContext = builtins.hasContext or (lib.hasPrefix builtins.storeDir);
36+
37+ canCleanSource = src:
38+ src ? _isLibCleanSourceWithEx
39+ || src ? _isLibCleanSourceWith
40+ || !(pathHasContext (toString src));
41+}
lib/default.nix+7
@@ -112,4 +112,11 @@ with haskellLib;
112 (mapAttrs (_: package: package.components.${group} // { recurseForDerivations = true; })
112 (mapAttrs (_: package: package.components.${group} // { recurseForDerivations = true; })
113 (filterAttrs (name: package: (package.isHaskell or false) && packageSel package) haskellPackages))
113 (filterAttrs (name: package: (package.isHaskell or false) && packageSel package) haskellPackages))
114 // { recurseForDerivations = true; };
114 // { recurseForDerivations = true; };
115+
116+ # Replacement for lib.cleanSourceWith that has a subDir argument.
117+ inherit (import ./clean-source-with.nix { inherit lib; }) cleanSourceWith canCleanSource;
118+
119+ # Use cleanSourceWith to filter just the files needed for a particular
120+ # component of a package
121+ cleanCabalComponent = import ./clean-cabal-component.nix { inherit lib cleanSourceWith; };
115}
122}
lib/import-and-filter-project.nixnew file+36
@@ -0,0 +1,36 @@
1+# This function takes the output of `callCabalProjectToNix` or
2+# `callStackToNix`. It imports the projectNix that was produced
3+# and combines it with the original source.
4+{ pkgs, haskellLib }:
5+{ projectNix, sourceRepos, src }:
6+let
7+ project = import "${projectNix}";
8+in {
9+ nix = projectNix;
10+ pkgs = project // {
11+ extras = hackage: let old = (project.extras hackage).packages; in {
12+ packages = pkgs.lib.attrsets.mapAttrs (name: value:
13+ if builtins.isFunction value
14+ then value
15+ else {...}@args:
16+ let oldPkg = import value args;
17+ packageSrc = if !pkgs.lib.strings.hasPrefix (toString projectNix) (toString oldPkg.src.content)
18+ then toString oldPkg.src.content
19+ else let
20+ subDir = pkgs.lib.strings.removePrefix "/" (
21+ pkgs.lib.strings.removePrefix (toString projectNix)
22+ (toString oldPkg.src.content));
23+ srcRepoPrefix = ".source-repository-packages/";
24+ in if pkgs.lib.strings.hasPrefix srcRepoPrefix subDir
25+ then
26+ pkgs.lib.lists.elemAt sourceRepos (
27+ pkgs.lib.strings.toInt (pkgs.lib.strings.removePrefix srcRepoPrefix subDir))
28+ else if haskellLib.canCleanSource src
29+ then haskellLib.cleanSourceWith { inherit src subDir; }
30+ else src + (if subDir == "" then "" else "/" + subDir);
31+ in oldPkg // {
32+ src = (pkgs.lib).mkDefault packageSrc;
33+ }) old;
34+ };
35+ };
36+}
modules/package.nix+89−1
@@ -19,7 +19,11 @@
19with lib;
19with lib;
20with types;
20with types;
21
21
22+# Work around issue that can cause _lots_ of files to be copied into the store.
23+# See https://github.com/NixOS/nixpkgs/pull/64691
24+let path = types.path // { check = x: types.path.check (x.origSrc or x); };
25+
22−{
26+in {
23 # This is how the Nix expressions generated by *-to-nix receive
27 # This is how the Nix expressions generated by *-to-nix receive
24 # their flags argument.
28 # their flags argument.
25 config._module.args = mod_args // { flags = config.flags; };
29 config._module.args = mod_args // { flags = config.flags; };
@@ -82,6 +86,46 @@ with types;
82 type = listOfFilteringNulls unspecified;
86 type = listOfFilteringNulls unspecified;
83 default = [];
87 default = [];
84 };
88 };
89+
90+ detailLevel = mkOption {
91+ type = str;
92+ default = "MinimalDetails";
93+ };
94+
95+ licenseFiles = mkOption {
96+ type = listOfFilteringNulls unspecified;
97+ default = [];
98+ };
99+
100+ dataDir = mkOption {
101+ type = str;
102+ default = "";
103+ };
104+
105+ dataFiles = mkOption {
106+ type = listOfFilteringNulls unspecified;
107+ default = [];
108+ };
109+
110+ extraSrcFiles = mkOption {
111+ type = listOfFilteringNulls unspecified;
112+ default = [];
113+ };
114+
115+ extraTmpFiles = mkOption {
116+ type = listOfFilteringNulls unspecified;
117+ default = [];
118+ };
119+
120+ extraDocFiles = mkOption {
121+ type = listOfFilteringNulls unspecified;
122+ default = [];
123+ };
124+
125+ cleanHpack = mkOption {
126+ type = bool;
127+ default = false;
128+ };
85 };
129 };
86
130
87 components = let
131 components = let
@@ -108,6 +152,50 @@ with types;
108 type = listOfFilteringNulls unspecified;
152 type = listOfFilteringNulls unspecified;
109 default = [];
153 default = [];
110 };
154 };
155+ modules = mkOption {
156+ type = listOfFilteringNulls unspecified;
157+ default = [];
158+ };
159+ asmSources = mkOption {
160+ type = listOfFilteringNulls unspecified;
161+ default = [];
162+ };
163+ cmmSources = mkOption {
164+ type = listOfFilteringNulls unspecified;
165+ default = [];
166+ };
167+ cSources = mkOption {
168+ type = listOfFilteringNulls unspecified;
169+ default = [];
170+ };
171+ cxxSources = mkOption {
172+ type = listOfFilteringNulls unspecified;
173+ default = [];
174+ };
175+ jsSources = mkOption {
176+ type = listOfFilteringNulls unspecified;
177+ default = [];
178+ };
179+ hsSourceDirs = mkOption {
180+ type = listOfFilteringNulls unspecified;
181+ default = [];
182+ };
183+ includeDirs = mkOption {
184+ type = listOfFilteringNulls unspecified;
185+ default = [];
186+ };
187+ includes = mkOption {
188+ type = listOfFilteringNulls unspecified;
189+ default = [];
190+ };
191+ mainPath = mkOption {
192+ type = listOfFilteringNulls unspecified;
193+ default = [];
194+ };
195+ extraSrcFiles = mkOption {
196+ type = listOfFilteringNulls unspecified;
197+ default = [];
198+ };
111 };
199 };
112 };
200 };
113 in {
201 in {
nix-tools/nix-tools-src.json+3−3
@@ -1,7 +1,7 @@
1{
1{
2 "url": "https://github.com/input-output-hk/nix-tools",
2 "url": "https://github.com/input-output-hk/nix-tools",
3− "rev": "3d021291ddf148220050adef350ac51bf27d415f",
3+ "rev": "a9f227d9238102fb424157156712ef9b64413096",
4− "date": "2019-05-31T11:38:58+08:00",
4+ "date": "2019-07-18T12:21:16+12:00",
5− "sha256": "1zgkmm1a3xhclwvnfcbcsqp9zl91g20csiirk2rqyn8k8vy8wwkb",
5+ "sha256": "19r5an3hrjn1a4mm2n0fhaa5b1fi975pyjcisbnrhwfajlqb362f",
6 "fetchSubmodules": false
6 "fetchSubmodules": false
7}
7}
nix-tools/pkgs.nix+7−7
@@ -7,7 +7,7 @@
7 "test-framework-hunit".revision = (((hackage."test-framework-hunit")."0.3.0.2").revisions).default;
7 "test-framework-hunit".revision = (((hackage."test-framework-hunit")."0.3.0.2").revisions).default;
8 "test-framework-hunit".flags.base4 = true;
8 "test-framework-hunit".flags.base4 = true;
9 "test-framework-hunit".flags.base3 = false;
9 "test-framework-hunit".flags.base3 = false;
10− "http-client".revision = (((hackage."http-client")."0.5.14").revisions).default;
10+ "http-client".revision = (((hackage."http-client")."0.6.4").revisions).default;
11 "http-client".flags.network-uri = true;
11 "http-client".flags.network-uri = true;
12 "cookie".revision = (((hackage."cookie")."0.4.4").revisions).default;
12 "cookie".revision = (((hackage."cookie")."0.4.4").revisions).default;
13 "void".revision = (((hackage."void")."0.7.3").revisions).default;
13 "void".revision = (((hackage."void")."0.7.3").revisions).default;
@@ -21,7 +21,6 @@
21 "semigroupoids".flags.containers = true;
21 "semigroupoids".flags.containers = true;
22 "semigroupoids".flags.contravariant = true;
22 "semigroupoids".flags.contravariant = true;
23 "free".revision = (((hackage."free")."5.1.1").revisions).default;
23 "free".revision = (((hackage."free")."5.1.1").revisions).default;
24− "tf-random".revision = (((hackage."tf-random")."0.5").revisions).default;
25 "Only".revision = (((hackage."Only")."0.1").revisions).default;
24 "Only".revision = (((hackage."Only")."0.1").revisions).default;
26 "cereal".revision = (((hackage."cereal")."0.5.8.0").revisions).default;
25 "cereal".revision = (((hackage."cereal")."0.5.8.0").revisions).default;
27 "cereal".flags.bytestring-builder = false;
26 "cereal".flags.bytestring-builder = false;
@@ -106,7 +105,7 @@
106 "distributive".flags.tagged = true;
105 "distributive".flags.tagged = true;
107 "asn1-encoding".revision = (((hackage."asn1-encoding")."0.9.5").revisions).default;
106 "asn1-encoding".revision = (((hackage."asn1-encoding")."0.9.5").revisions).default;
108 "vector-th-unbox".revision = (((hackage."vector-th-unbox")."0.2.1.6").revisions).default;
107 "vector-th-unbox".revision = (((hackage."vector-th-unbox")."0.2.1.6").revisions).default;
109− "QuickCheck".revision = (((hackage."QuickCheck")."2.12.6.1").revisions).default;
108+ "QuickCheck".revision = (((hackage."QuickCheck")."2.13.1").revisions).default;
110 "QuickCheck".flags.templatehaskell = true;
109 "QuickCheck".flags.templatehaskell = true;
111 "scientific".revision = (((hackage."scientific")."0.3.6.2").revisions).default;
110 "scientific".revision = (((hackage."scientific")."0.3.6.2").revisions).default;
112 "scientific".flags.integer-simple = false;
111 "scientific".flags.integer-simple = false;
@@ -124,6 +123,7 @@
124 "optparse-applicative".revision = (((hackage."optparse-applicative")."0.14.3.0").revisions).default;
123 "optparse-applicative".revision = (((hackage."optparse-applicative")."0.14.3.0").revisions).default;
125 "network".revision = (((hackage."network")."3.1.0.0").revisions).default;
124 "network".revision = (((hackage."network")."3.1.0.0").revisions).default;
126 "connection".revision = (((hackage."connection")."0.3.0").revisions).default;
125 "connection".revision = (((hackage."connection")."0.3.0").revisions).default;
126+ "splitmix".revision = (((hackage."splitmix")."0.0.2").revisions).default;
127 "async".revision = (((hackage."async")."2.2.1").revisions).default;
127 "async".revision = (((hackage."async")."2.2.1").revisions).default;
128 "async".flags.bench = false;
128 "async".flags.bench = false;
129 "dlist".revision = (((hackage."dlist")."0.8.0.6").revisions).default;
129 "dlist".revision = (((hackage."dlist")."0.8.0.6").revisions).default;
@@ -216,9 +216,9 @@
216 "reflection".revision = (((hackage."reflection")."2.1.4").revisions).default;
216 "reflection".revision = (((hackage."reflection")."2.1.4").revisions).default;
217 "reflection".flags.slow = false;
217 "reflection".flags.slow = false;
218 "reflection".flags.template-haskell = true;
218 "reflection".flags.template-haskell = true;
219− "these".revision = (((hackage."these")."0.7.6").revisions).default;
219+ "these".revision = (((hackage."these")."0.8").revisions).default;
220 "regex-tdfa-text".revision = (((hackage."regex-tdfa-text")."1.0.0.3").revisions).default;
220 "regex-tdfa-text".revision = (((hackage."regex-tdfa-text")."1.0.0.3").revisions).default;
221− "dependent-sum".revision = (((hackage."dependent-sum")."0.4").revisions).default;
221+ "dependent-sum".revision = (((hackage."dependent-sum")."0.5").revisions).default;
222 "socks".revision = (((hackage."socks")."0.6.0").revisions).default;
222 "socks".revision = (((hackage."socks")."0.6.0").revisions).default;
223 "streaming-commons".revision = (((hackage."streaming-commons")."0.2.1.0").revisions).default;
223 "streaming-commons".revision = (((hackage."streaming-commons")."0.2.1.0").revisions).default;
224 "streaming-commons".flags.use-bytestring-builder = false;
224 "streaming-commons".flags.use-bytestring-builder = false;
@@ -266,6 +266,7 @@
266 "deriving-compat".flags.new-functor-classes = true;
266 "deriving-compat".flags.new-functor-classes = true;
267 "text".revision = (((hackage."text")."1.2.3.1").revisions).default;
267 "text".revision = (((hackage."text")."1.2.3.1").revisions).default;
268 "Cabal".revision = (((hackage."Cabal")."2.4.0.1").revisions).default;
268 "Cabal".revision = (((hackage."Cabal")."2.4.0.1").revisions).default;
269+ "assoc".revision = (((hackage."assoc")."1").revisions).default;
269 "Diff".revision = (((hackage."Diff")."0.3.4").revisions).default;
270 "Diff".revision = (((hackage."Diff")."0.3.4").revisions).default;
270 "unordered-containers".revision = (((hackage."unordered-containers")."0.2.10.0").revisions).default;
271 "unordered-containers".revision = (((hackage."unordered-containers")."0.2.10.0").revisions).default;
271 "unordered-containers".flags.debug = false;
272 "unordered-containers".flags.debug = false;
@@ -292,7 +293,7 @@
292 "prettyprinter".flags.buildreadme = false;
293 "prettyprinter".flags.buildreadme = false;
293 "cryptohash-sha512".revision = (((hackage."cryptohash-sha512")."0.11.100.1").revisions).default;
294 "cryptohash-sha512".revision = (((hackage."cryptohash-sha512")."0.11.100.1").revisions).default;
294 "tasty-hunit".revision = (((hackage."tasty-hunit")."0.10.0.2").revisions).default;
295 "tasty-hunit".revision = (((hackage."tasty-hunit")."0.10.0.2").revisions).default;
295− "pretty-show".revision = (((hackage."pretty-show")."1.9.5").revisions).default;
296+ "pretty-show".revision = (((hackage."pretty-show")."1.8.2").revisions).default;
296 "transformers".revision = (((hackage."transformers")."0.5.6.2").revisions).default;
297 "transformers".revision = (((hackage."transformers")."0.5.6.2").revisions).default;
297 "hashable".revision = (((hackage."hashable")."1.2.7.0").revisions).default;
298 "hashable".revision = (((hackage."hashable")."1.2.7.0").revisions).default;
298 "hashable".flags.sse2 = true;
299 "hashable".flags.sse2 = true;
@@ -354,7 +355,6 @@
354 "array".revision = (((hackage."array")."0.5.3.0").revisions).default;
355 "array".revision = (((hackage."array")."0.5.3.0").revisions).default;
355 "repline".revision = (((hackage."repline")."0.2.1.0").revisions).default;
356 "repline".revision = (((hackage."repline")."0.2.1.0").revisions).default;
356 "xml".revision = (((hackage."xml")."1.3.14").revisions).default;
357 "xml".revision = (((hackage."xml")."1.3.14").revisions).default;
357− "erf".revision = (((hackage."erf")."2.0.0.0").revisions).default;
358 "lens-family-core".revision = (((hackage."lens-family-core")."1.2.3").revisions).default;
358 "lens-family-core".revision = (((hackage."lens-family-core")."1.2.3").revisions).default;
359 "integer-gmp".revision = (((hackage."integer-gmp")."1.0.2.0").revisions).default;
359 "integer-gmp".revision = (((hackage."integer-gmp")."1.0.2.0").revisions).default;
360 };
360 };
test/cabal-source-repo/default.nix+3−3
@@ -1,14 +1,14 @@
1−{ stdenv, mkCabalProjectPkgSet, callCabalProjectToNix }:
1+{ stdenv, mkCabalProjectPkgSet, callCabalProjectToNix, importAndFilterProject }:
2
2
3with stdenv.lib;
3with stdenv.lib;
4
4
5let
5let
6 pkgSet = mkCabalProjectPkgSet {
6 pkgSet = mkCabalProjectPkgSet {
7− plan-pkgs = import (callCabalProjectToNix {
7+ plan-pkgs = (importAndFilterProject (callCabalProjectToNix {
8 index-state = "2019-04-30T00:00:00Z";
8 index-state = "2019-04-30T00:00:00Z";
9 # reuse the cabal-simple test project
9 # reuse the cabal-simple test project
10 src = ./.;
10 src = ./.;
11− });
11+ })).pkgs;
12 };
12 };
13 packages = pkgSet.config.hsPkgs;
13 packages = pkgSet.config.hsPkgs;
14in
14in
test/call-cabal-project-to-nix/default.nix+3−3
@@ -1,14 +1,14 @@
1−{ stdenv, mkCabalProjectPkgSet, callCabalProjectToNix }:
1+{ stdenv, mkCabalProjectPkgSet, callCabalProjectToNix, importAndFilterProject }:
2
2
3with stdenv.lib;
3with stdenv.lib;
4
4
5let
5let
6 pkgSet = mkCabalProjectPkgSet {
6 pkgSet = mkCabalProjectPkgSet {
7− plan-pkgs = import (callCabalProjectToNix {
7+ plan-pkgs = (importAndFilterProject (callCabalProjectToNix {
8 index-state = "2019-04-30T00:00:00Z";
8 index-state = "2019-04-30T00:00:00Z";
9 # reuse the cabal-simple test project
9 # reuse the cabal-simple test project
10 src = ../cabal-simple;
10 src = ../cabal-simple;
11− });
11+ })).pkgs;
12 };
12 };
13 packages = pkgSet.config.hsPkgs;
13 packages = pkgSet.config.hsPkgs;
14in
14in
test/call-stack-to-nix/default.nix+3−3
@@ -1,12 +1,12 @@
1−{ stdenv, mkStackPkgSet, callStackToNix }:
1+{ stdenv, mkStackPkgSet, callStackToNix, importAndFilterProject }:
2
2
3with stdenv.lib;
3with stdenv.lib;
4
4
5let
5let
6 pkgSet = mkStackPkgSet {
6 pkgSet = mkStackPkgSet {
7− stack-pkgs = import (callStackToNix {
7+ stack-pkgs = (importAndFilterProject (callStackToNix {
8 src = ../stack-simple;
8 src = ../stack-simple;
9− });
9+ })).pkgs;
10 pkg-def-extras = [];
10 pkg-def-extras = [];
11 modules = [];
11 modules = [];
12 };
12 };