Restructuring files

This commit is contained in:
Judson
2017-05-27 15:19:34 -07:00
parent 022be78eb2
commit 998d011e42
13 changed files with 56 additions and 41 deletions
@@ -1,24 +0,0 @@
{ test, lib, ...}:
{
equal = expected: actual:
if actual == expected then
(test.passed "= ${toString expected}") else
(test.failed "'${toString actual}'(${builtins.typeOf actual}) != '${toString expected}'(${builtins.typeOf expected})");
beASet = actual:
if builtins.isAttrs actual then
(test.passed "is a set") else
(test.failed "is not a set, was ${builtins.typeOf actual}: ${toString actual}");
haveKeys = expected: actual:
if builtins.all
(ex: builtins.any (ac: ex == ac) (builtins.attrNames actual))
expected then
(test.passed "has expected keys") else
(test.failed "keys differ: expected [${lib.concatStringsSep ";" expected}] have [${lib.concatStringsSep ";" (builtins.attrNames actual)}]");
havePrefix = expected: actual:
if lib.hasPrefix expected actual then
(test.passed "has prefix '${expected}'") else
(test.failed "prefix '${expected}' not found in '${actual}'");
}
@@ -1,140 +0,0 @@
{ stdenv, runCommand, ruby, lib
, defaultGemConfig, buildRubyGem, buildEnv
, makeWrapper
, bundler
}@defs:
{
name
, pname ? name
, gemfile
, lockfile
, gemset
, gemdir
, ruby ? defs.ruby
, gemConfig ? defaultGemConfig
, postBuild ? null
, document ? []
, meta ? {}
, groups ? ["default"]
, ignoreCollisions ? false
, ...
}@args:
with import ./functions.nix { inherit lib gemConfig; };
let
importedGemset = import gemset;
filteredGemset = filterGemset { inherit ruby groups; } importedGemset;
configuredGemset = lib.flip lib.mapAttrs filteredGemset (name: attrs:
applyGemConfigs (attrs // { inherit ruby; gemName = name; })
);
hasBundler = builtins.hasAttr "bundler" filteredGemset;
bundler =
if hasBundler then gems.bundler
else defs.bundler.override (attrs: { inherit ruby; });
gems = lib.flip lib.mapAttrs configuredGemset (name: attrs: buildGem name attrs);
copyIfBundledByPath = { bundledByPath ? false, ...}@main:
(if bundledByPath then ''
cp -a ${gemdir}/* $out/
'' else ""
);
maybeCopyAll = pname: if pname == null then "" else
let
mainGem = gems."${pname}" or (throw "bundlerEnv: gem ${pname} not found");
in
copyIfBundledByPath mainGem;
# We have to normalize the Gemfile.lock, otherwise bundler tries to be
# helpful by doing so at run time, causing executables to immediately bail
# out. Yes, I'm serious.
confFiles = runCommand "gemfile-and-lockfile" {} ''
mkdir -p $out
${maybeCopyAll pname}
cp ${gemfile} $out/Gemfile || ls -l $out/Gemfile
cp ${lockfile} $out/Gemfile.lock || ls -l $out/Gemfile.lock
'';
buildGem = name: attrs: (
let
gemAttrs = composeGemAttrs ruby gems name attrs;
in
if gemAttrs.type == "path" then
pathDerivation gemAttrs
else
buildRubyGem gemAttrs
);
envPaths = lib.attrValues gems ++ lib.optional (!hasBundler) bundler;
basicEnv = buildEnv {
inherit ignoreCollisions;
name = if name == null then pname else name;
#name = pname;
paths = envPaths;
pathsToLink = [ "/lib" ];
postBuild = genStubsScript (defs // args // {
inherit confFiles bundler groups;
binPaths = envPaths;
}) + lib.optionalString (postBuild != null) postBuild;
meta = { platforms = ruby.meta.platforms; } // meta;
passthru = rec {
inherit ruby bundler gems mainGem confFiles; # drvName;
wrappedRuby =
stdenv.mkDerivation {
name = "wrapped-ruby-${pname}";
nativeBuildInputs = [ makeWrapper ];
buildCommand = ''
mkdir -p $out/bin
for i in ${ruby}/bin/*; do
makeWrapper "$i" $out/bin/$(basename "$i") \
--set BUNDLE_GEMFILE ${confFiles}/Gemfile \
--set BUNDLE_PATH ${basicEnv}/${ruby.gemPath} \
--set BUNDLE_FROZEN 1 \
--set GEM_HOME ${basicEnv}/${ruby.gemPath} \
--set GEM_PATH ${basicEnv}/${ruby.gemPath}
done
'';
};
env = let
irbrc = builtins.toFile "irbrc" ''
if !(ENV["OLD_IRBRC"].nil? || ENV["OLD_IRBRC"].empty?)
require ENV["OLD_IRBRC"]
end
require 'rubygems'
require 'bundler/setup'
'';
in stdenv.mkDerivation {
name = "${pname}-interactive-environment";
nativeBuildInputs = [ wrappedRuby basicEnv ];
shellHook = ''
export OLD_IRBRC="$IRBRC"
export IRBRC=${irbrc}
'';
buildCommand = ''
echo >&2 ""
echo >&2 "*** Ruby 'env' attributes are intended for interactive nix-shell sessions, not for building! ***"
echo >&2 ""
exit 1
'';
};
};
};
in
basicEnv
@@ -24,7 +24,7 @@
}@args:
let
inherit (import ./functions.nix {inherit lib ruby gemConfig groups; }) genStubsScript;
inherit (import ../bundled-common/functions.nix {inherit lib ruby gemConfig groups; }) genStubsScript;
drvName =
if name != null then lib.traceVal name
@@ -43,7 +43,7 @@ let
if gemset == null then gemdir + "/gemset.nix"
else gemset;
basicEnv = (callPackage ./basic.nix {}) (args // { inherit pname name gemdir;
basicEnv = (callPackage ../bundled-common {}) (args // { inherit pname name gemdir;
gemfile = gemfile';
lockfile = lockfile';
gemset = gemset';
@@ -1,53 +0,0 @@
{ lib, gemConfig, ... }:
rec {
filterGemset = {ruby, groups,...}@env: gemset: lib.filterAttrs (name: attrs: platformMatches ruby attrs && groupMatches groups attrs) gemset;
platformMatches = {rubyEngine, version, ...}@ruby: attrs: (
!(attrs ? "platforms") ||
builtins.length attrs.platforms == 0 ||
builtins.any (platform:
platform.engine == rubyEngine &&
(!(platform ? "version") || platform.version == version.majMin)
) attrs.platforms
);
groupMatches = groups: attrs: (
!(attrs ? "groups") ||
builtins.any (gemGroup: builtins.any (group: group == gemGroup) groups) attrs.groups
);
applyGemConfigs = attrs:
(if gemConfig ? "${attrs.gemName}"
then attrs // gemConfig."${attrs.gemName}" attrs
else attrs);
genStubsScript = { lib, ruby, confFiles, bundler, groups, binPaths, ... }: ''
${ruby}/bin/ruby ${./gen-bin-stubs.rb} \
"${ruby}/bin/ruby" \
"${confFiles}/Gemfile" \
"$out/${ruby.gemPath}" \
"${bundler}/${ruby.gemPath}" \
${lib.escapeShellArg binPaths} \
${lib.escapeShellArg groups}
'';
pathDerivation = { gemName, version, path, ... }:
let
res = {
type = "derivation";
bundledByPath = true;
name = gemName;
version = version;
outPath = path;
outputs = [ "out" ];
out = res;
outputName = "out";
};
in res;
composeGemAttrs = ruby: gems: name: attrs: ((removeAttrs attrs ["source" "platforms"]) // attrs.source // {
inherit ruby;
gemName = name;
gemPath = map (gemName: gems."${gemName}") (attrs.dependencies or []);
});
}
@@ -1,47 +0,0 @@
require 'rbconfig'
require 'rubygems'
require 'rubygems/specification'
require 'fileutils'
# args/settings
out = ENV["out"]
ruby = ARGV[0]
gemfile = ARGV[1]
bundle_path = ARGV[2]
bundler_gem_path = ARGV[3]
paths = ARGV[4].split
groups = ARGV[5].split
# generate binstubs
FileUtils.mkdir_p("#{out}/bin")
paths.each do |path|
next unless File.directory?("#{path}/nix-support/gem-meta")
name = File.read("#{path}/nix-support/gem-meta/name")
executables = File.read("#{path}/nix-support/gem-meta/executables").split
executables.each do |exe|
File.open("#{out}/bin/#{exe}", "w") do |f|
f.write(<<-EOF)
#!#{ruby}
#
# This file was generated by Nix.
#
# The application '#{exe}' is installed as part of a gem, and
# this file is here to facilitate running it.
#
ENV["BUNDLE_GEMFILE"] = #{gemfile.dump}
ENV["BUNDLE_PATH"] = #{bundle_path.dump}
ENV['BUNDLE_FROZEN'] = '1'
Gem.use_paths(#{bundler_gem_path.dump}, ENV["GEM_PATH"])
require 'bundler'
Bundler.setup(#{groups.map(&:dump).join(', ')})
load Gem.bin_path(#{name.dump}, #{exe.dump})
EOF
FileUtils.chmod("+x", "#{out}/bin/#{exe}")
end
end
end
@@ -1,2 +0,0 @@
#!/usr/bin/env bash
nix-build -E 'with import <nixpkgs> { }; callPackage ./test.nix {}' --show-trace && cat result
@@ -1,33 +0,0 @@
{ stdenv, lib, ruby, callPackage, ... }:
let
real = {
inherit (stdenv) mkDerivation;
};
mkDerivation = {name, ...}@argSet:
derivation {
inherit name;
text = (builtins.toJSON (lib.filterAttrs ( n: v: builtins.any (x: x == n) ["name" "system"]) argSet));
builder = stdenv.shell;
args = [ "-c" "echo $(<$textPath) > $out"];
system = stdenv.system;
passAsFile = ["text"];
};
fetchurl = {url?"", urls ? [],...}: "fetchurl:${if urls == [] then url else builtins.head urls}";
stdenv' = stdenv // {
inherit mkDerivation;
stubbed = true;
};
ruby' = ruby // {
stdenv = stdenv';
stubbed = true;
};
in
{
ruby = ruby';
buildRubyGem = callPackage ../gem {
inherit fetchurl;
ruby = ruby';
};
stdenv = stdenv';
}
@@ -1,20 +0,0 @@
with builtins;
let
withIndexes = list: genList (idx: (elemAt list idx) // {index = idx;}) (length list);
testLine = report: "${okStr report} ${toString report.index} ${report.description}" + testDirective report + testYaml report;
testDirective = report: "";
testYaml = report: "";
okStr = { result, ...}: if result == "pass" then "ok" else "not ok";
in
{
output = reports: ''
TAP version 13
1..${toString (length reports)}'' + (foldl' (l: r: l + "\n" + r) "" (map testLine (withIndexes reports))) + ''
# Finished at ${toString currentTime}
'';
}
@@ -1,28 +1,9 @@
/*
Run with:
nix-build -E 'with import <nixpkgs> { }; callPackage ./test.nix {}' --show-trace; and cat result
Confusingly, the ideal result ends with something like:
error: build of /nix/store/3245f3dcl2wxjs4rci7n069zjlz8qg85-test-results.tap.drv failed
*/
{ stdenv, writeText, lib, ruby, defaultGemConfig, callPackage }@defs:
{ stdenv, writeText, lib, ruby, defaultGemConfig, callPackage, test, stubs, should}@defs:
let
test = import ./testing.nix;
tap = import ./tap-support.nix;
stubs = import ./stubs.nix defs;
should = import ./assertions.nix { inherit test lib; };
basicEnv = callPackage ./basic.nix stubs;
bundlerEnv = callPackage ./default.nix stubs // {
inherit basicEnv;
basicEnv = callPackage ../bundled-common stubs;
};
testConfigs = {
inherit lib;
gemConfig = defaultGemConfig;
};
functions = (import ./functions.nix testConfigs);
justName = bundlerEnv {
name = "test-0.1.2";
gemset = ./test/gemset.nix;
@@ -35,21 +16,8 @@ let
gemfile = ./test/Gemfile;
lockfile = ./test/Gemfile.lock;
};
results = builtins.concatLists [
(test.run "Filter empty gemset" {} (set: functions.filterGemset {inherit ruby; groups = ["default"]; } set == {}))
( let gemSet = { test = { groups = ["x" "y"]; }; };
in
test.run "Filter matches a group" gemSet (set: functions.filterGemset {inherit ruby; groups = ["y" "z"];} set == gemSet))
( let gemSet = { test = { platforms = []; }; };
in
test.run "Filter matches empty platforms list" gemSet (set: functions.filterGemset {inherit ruby; groups = [];} set == gemSet))
( let gemSet = { test = { platforms = [{engine = ruby.rubyEngine; version = ruby.version.majMin;}]; }; };
in
test.run "Filter matches on platform" gemSet (set: functions.filterGemset {inherit ruby; groups = [];} set == gemSet))
( let gemSet = { test = { groups = ["x" "y"]; }; };
in
test.run "Filter excludes based on groups" gemSet (set: functions.filterGemset {inherit ruby; groups = ["a" "b"];} set == {}))
in
builtins.concatLists [
(test.run "bundlerEnv { name }" justName {
name = should.equal "test-0.1.2";
})
@@ -62,6 +30,4 @@ let
postBuild = should.havePrefix "/nix/store";
}
])
];
in
writeText "test-results.tap" (tap.output results)
]
@@ -1,62 +0,0 @@
with builtins;
let
/*
underTest = {
x = {
a = 1;
b = "2";
};
};
tests = [
(root: false)
{
x = [
(set: true)
{
a = (a: a > 1);
b = (b: b == "3");
}
];
}
];
results = run "Examples" underTest tests;
*/
passed = desc: {
result = "pass";
description = desc;
};
failed = desc: {
result = "failed";
description = desc;
};
prefixName = name: res: {
inherit (res) result;
description = "${name}: ${res.description}";
};
run = name: under: tests: if isList tests then
(concatLists (map (run name under) tests))
else if isAttrs tests then
(concatLists (map (
subName: run (name + "." + subName) (if hasAttr subName under then getAttr subName under else "<MISSING!>") (getAttr subName tests)
) (attrNames tests)))
else if isFunction tests then
let
res = tests under;
in
if isBool res then
[
(prefixName name (if tests under then passed "passed" else failed "failed"))
]
else
[ (prefixName name res) ]
else [
failed (name ": not a function, list or set")
];
in
{ inherit run passed failed; }