Skip to content

Commit db69890

Browse files
author
Richard Feldman
authored
Merge pull request #106 from michaelglass/avoid-pipes
Avoid pipes
2 parents dc9668d + 959fda0 commit db69890

File tree

13 files changed

+339
-138
lines changed

13 files changed

+339
-138
lines changed

.travis.yml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1-
language: node_js
2-
node_js:
3-
- "0.12"
1+
sudo: false
2+
3+
env:
4+
matrix:
5+
- ELM_VERSION=0.16.0 TARGET_NODE_VERSION=node
6+
- ELM_VERSION=0.16.0 TARGET_NODE_VERSION=0.12
7+
8+
install:
9+
- nvm install $TARGET_NODE_VERSION
10+
- nvm use $TARGET_NODE_VERSION
11+
- node --version
12+
- npm --version
13+
- npm install -g elm@$ELM_VERSION
14+
15+
script: ./ci.sh

BuildFromSource.hs

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
{-| This script builds any version of the Elm Platform from source.
2+
Before you use it, make sure you have the Haskell Platform with a recent
3+
version of cabal.
4+
5+
To install a released version of Elm, you will run something like this:
6+
7+
runhaskell BuildFromSource.hs 0.15.1
8+
9+
Before you do that, in some directory of your choosing, add
10+
wherever/Elm-Platform/0.15.1/.cabal-sandbox/bin to your PATH.
11+
12+
Then, run the above. You will now actually have a new directory for the
13+
Elm Platform, like this:
14+
15+
Elm-Platform/0.15.1/
16+
elm-make/ -- git repo for the build tool, ready to edit
17+
elm-repl/ -- git repo for the REPL, ready to edit
18+
...
19+
.cabal-sandbox/ -- various build files
20+
21+
All of the executables you need are in .cabal-sandbox/bin, which is on
22+
your PATH and thus can be used from anywhere.
23+
24+
You can build many versions of the Elm Platform, so it is possible to have
25+
Elm-Platform/0.15.1/ and Elm-Platform/0.13/ with no problems. It is up to you
26+
to manage your PATH variable or symlinks though.
27+
28+
To get set up with the master branch of all Elm Platform projects, run this:
29+
30+
runhaskell BuildFromSource.hs master
31+
32+
From there you can start developing on any of the projects, switching branches
33+
and testing interactions between projects.
34+
-}
35+
module Main where
36+
37+
import qualified Data.List as List
38+
import qualified Data.Map as Map
39+
import System.Directory (createDirectoryIfMissing,
40+
getCurrentDirectory, setCurrentDirectory)
41+
import System.Environment (getArgs)
42+
import System.Exit (ExitCode, exitFailure)
43+
import System.FilePath ((</>))
44+
import System.IO (hPutStrLn, stderr)
45+
import System.Process (rawSystem)
46+
47+
48+
(=:) = (,)
49+
50+
configs :: Map.Map String [(String, String)]
51+
configs =
52+
Map.fromList
53+
[
54+
"master" =:
55+
[ "elm-compiler" =: "master"
56+
, "elm-package" =: "master"
57+
, "elm-make" =: "master"
58+
, "elm-reactor" =: "master"
59+
, "elm-repl" =: "master"
60+
]
61+
,
62+
"0.15.1" =:
63+
[ "elm-compiler" =: "0.15.1"
64+
, "elm-package" =: "0.5.1"
65+
, "elm-make" =: "0.2"
66+
]
67+
,
68+
"0.15" =:
69+
[ "elm-compiler" =: "0.15"
70+
, "elm-package" =: "0.5"
71+
, "elm-make" =: "0.1.2"
72+
, "elm-reactor" =: "0.3.1"
73+
, "elm-repl" =: "0.4.1"
74+
]
75+
,
76+
"0.14.1" =:
77+
[ "elm-compiler" =: "0.14.1"
78+
, "elm-package" =: "0.4"
79+
, "elm-make" =: "0.1.1"
80+
, "elm-reactor" =: "0.3"
81+
, "elm-repl" =: "0.4"
82+
]
83+
,
84+
"0.14" =:
85+
[ "elm-compiler" =: "0.14"
86+
, "elm-package" =: "0.2"
87+
, "elm-make" =: "0.1"
88+
, "elm-reactor" =: "0.2"
89+
, "elm-repl" =: "0.4"
90+
]
91+
,
92+
"0.13" =:
93+
[ "Elm" =: "0.13"
94+
, "elm-reactor" =: "0.1"
95+
, "elm-repl" =: "0.3"
96+
, "elm-get" =: "0.1.3"
97+
]
98+
,
99+
"0.12.3" =:
100+
[ "Elm" =: "0.12.3"
101+
, "elm-server" =: "0.11.0.1"
102+
, "elm-repl" =: "0.2.2.1"
103+
, "elm-get" =: "0.1.2"
104+
]
105+
]
106+
107+
108+
main :: IO ()
109+
main =
110+
do args <- getArgs
111+
case args of
112+
[version] | Map.member version configs ->
113+
let artifactDirectory = "Elm-Platform" </> version
114+
repos = configs Map.! version
115+
in
116+
makeRepos artifactDirectory version repos
117+
118+
_ ->
119+
do hPutStrLn stderr $
120+
"Expecting one of the following values as an argument:\n" ++
121+
" " ++ List.intercalate ", " (Map.keys configs)
122+
exitFailure
123+
124+
125+
makeRepos :: FilePath -> String -> [(String, String)] -> IO ()
126+
makeRepos artifactDirectory version repos =
127+
do createDirectoryIfMissing True artifactDirectory
128+
setCurrentDirectory artifactDirectory
129+
root <- getCurrentDirectory
130+
mapM_ (uncurry (makeRepo root)) repos
131+
132+
cabal [ "update" ]
133+
134+
-- create a sandbox for installation
135+
cabal [ "sandbox", "init" ]
136+
137+
-- add each of the sub-directories as a sandbox source
138+
cabal ([ "sandbox", "add-source" ] ++ map fst repos)
139+
140+
-- install all of the packages together in order to resolve transitive dependencies robustly
141+
-- (install the dependencies a bit more quietly than the elm packages)
142+
cabal ([ "install", "-j", "--only-dependencies", "--ghc-options=\"-w\"" ] ++ (if version <= "0.15.1" then [ "--constraint=fsnotify<0.2" ] else []) ++ map fst repos)
143+
cabal ([ "install", "-j", "--ghc-options=\"-XFlexibleContexts\"" ] ++ filter (/= "elm-reactor") (map fst repos))
144+
145+
return ()
146+
147+
makeRepo :: FilePath -> String -> String -> IO ()
148+
makeRepo root projectName version =
149+
do -- get the right version of the repo
150+
git [ "clone", "https://github.com/elm-lang/" ++ projectName ++ ".git" ]
151+
setCurrentDirectory projectName
152+
git [ "checkout", version, "--quiet" ]
153+
154+
-- move back into the root
155+
setCurrentDirectory root
156+
157+
158+
-- HELPER FUNCTIONS
159+
160+
cabal :: [String] -> IO ExitCode
161+
cabal = rawSystem "cabal"
162+
163+
git :: [String] -> IO ExitCode
164+
git = rawSystem "git"

bin/elm-test

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
var processTitle = "elm-test"
44

5-
process.title = 'elm-test';
5+
process.title = processTitle;
66

77
var compile = require("node-elm-compiler").compile,
88
suffix = require("../elm-io-ports.js"),
@@ -12,7 +12,16 @@ var compile = require("node-elm-compiler").compile,
1212
util = require("util"),
1313
_ = require("lodash"),
1414
childProcess = require("child_process"),
15-
elm = require("elm");
15+
findup = require("findup-sync");
16+
17+
var elm = {
18+
'elm-package': 'elm-package'
19+
};
20+
21+
if (process.argv[2] == "--version") {
22+
console.log(require(path.join(__dirname, "..", "package.json")).version);
23+
process.exit(0);
24+
}
1625

1726
if (process.argv[2] == "init") {
1827
var copyTemplate = function(templateName) {
@@ -33,15 +42,17 @@ if (process.argv[2] == "init") {
3342
childProcess.execSync(elm["elm-package"] + " " + command + elmOptions, {stdio:[0,1,2]});
3443
}
3544

36-
execElmPackageSync("install deadfoxygrandpa/Elm-Test");
37-
execElmPackageSync("install maxsnew/IO");
45+
copyTemplate("elm-package.json");
46+
execElmPackageSync("install deadfoxygrandpa/elm-test");
47+
execElmPackageSync("install laszlopandy/elm-console");
3848
copyTemplate("TestRunner.elm");
3949
copyTemplate("Tests.elm");
4050
process.exit(0);
4151
}
4252

43-
var testFile = process.argv[2],
44-
cwd = __dirname;
53+
var testFile = process.argv[2],
54+
cwd = __dirname,
55+
pathToMake = undefined;
4556

4657
function spawnCompiler(cmd, args, opts) {
4758
var compilerOpts = _.defaults({stdio: ["inherit", "pipe", "inherit"]}, opts);
@@ -51,7 +62,7 @@ function spawnCompiler(cmd, args, opts) {
5162

5263
if (typeof testFile !== "string") {
5364
console.log("Usage: elm-test init [--yes] # Create example tests\n");
54-
console.log("Usage: elm-test TESTFILE # Run tests\n");
65+
console.log("Usage: elm-test TESTFILE [--compiler /path/to/compiler] # Run tests\n");
5566
process.exit(1);
5667
}
5768

@@ -60,18 +71,27 @@ if (!fs.existsSync(testFile)) {
6071
process.exit(1);
6172
}
6273

63-
temp.open('elm_test_', function(err, info) {
64-
var dest = info.path;
65-
var compileProcess = compile([testFile], {output: dest, spawn: spawnCompiler});
74+
if (process.argv[3] == "--compiler" || process.argv[3] == "-c") {
75+
pathToMake = process.argv[4];
6676

67-
console.log("Compiling", testFile);
77+
if (!pathToMake) {
78+
console.error("The --compiler option must be given a path to an elm-make executable.");
79+
process.exit(1);
80+
}
81+
}
82+
83+
temp.open({ prefix:'elm_test_', suffix:'.js' }, function(err, info) {
84+
var dest = info.path;
85+
var compileProcess = compile( [testFile],
86+
{output: dest, spawn: spawnCompiler, pathToMake: pathToMake});
6887

6988
compileProcess.stdout.setEncoding("utf8")
7089
compileProcess.stdout.on("data", function(data) {
7190
// Explicitly strip out the "Successfully generated" message.
7291
// This avoids the nasty compiler output message for the temp file, e.g.
7392
// "Successfully generated /var/folders/f2/afd9fg0acfg32/elm_test_3423940"
74-
if ((typeof data === "string") && !data.match(/^Successfully generated /)) {
93+
// Also strip out "Success! Compiled 1 module."
94+
if ((typeof data === "string") && !/^Success/.test(data)) {
7595
console.log(data);
7696
}
7797
});
@@ -83,23 +103,24 @@ temp.open('elm_test_', function(err, info) {
83103

84104
console.log("Successfully compiled", testFile);
85105

86-
var runnerOpts = {stdio: ["pipe", "inherit", "inherit"]};
87-
var runnerProcess = childProcess.spawn("node", [], runnerOpts);
88-
89-
runnerProcess.on('exit', function (exitCode) {
90-
process.exit(exitCode);
91-
});
106+
// append suffix to temp file
107+
fs.appendFile(dest, suffix, function(err){
108+
if (err) throw(err);
92109

93-
var reader = fs.createReadStream(dest);
110+
console.log("Bootstrapped test script")
94111

95-
reader.on("end", function() {
96-
runnerProcess.stdin.write(suffix);
112+
// add node_modules to NODE_PATH so the temporary file can require
113+
// local modules
114+
var pathToNodeModules = findup("node_modules");
115+
process.env.NODE_PATH = _.compact([process.env.NODE_PATH, pathToNodeModules]).join(':');
97116

98-
runnerProcess.stdin.end();
99-
})
117+
var runnerProcess = childProcess.spawn("node", [dest], {stdio: 'inherit'});
100118

101-
reader.pipe(runnerProcess.stdin);
119+
runnerProcess.on('exit', function (exitCode) {
120+
process.exit(exitCode);
121+
});
102122

103-
console.log("Running tests...");
123+
console.log("Running tests...");
124+
});
104125
});
105126
});

ci.sh

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,48 @@
22

33
set -e
44

5+
function assertTestFailure() {
6+
elm-package install --yes
7+
elm-test "$1" | tee "$1".test.log
8+
if test ${PIPESTATUS[0]} -ne 1; then
9+
echo "$0: ERROR: $1: Expected tests to fail" >&2
10+
exit 1
11+
fi
12+
}
13+
14+
function assertTestSuccess() {
15+
elm-package install --yes
16+
elm-test "$1" | tee "$1".test.log
17+
if test ${PIPESTATUS[0]} -ne 0; then
18+
echo "$0: ERROR: $1: Expected tests to pass" >&2
19+
exit 1
20+
fi
21+
}
22+
523
echo "$0: Installing elm-test..."
624
npm install --global
725

26+
echo "$0: Verifying installed elm-test version..."
27+
elm-test --version
28+
29+
echo "$0: Testing examples..."
30+
cd examples
31+
assertTestSuccess PassingTests.elm
32+
assertTestFailure FailingTests.elm
33+
cd ..
34+
835
echo "$0: Testing elm-test init..."
9-
mkdir tmp
36+
mkdir -p tmp
1037
cd tmp
1138
elm-test init --yes
12-
elm-test TestRunner.elm | tee test.log
13-
if test ${PIPESTATUS[0]} -ne 1; then
14-
echo "$0: ERROR: Expected example tests to fail" >&2
15-
exit 1
16-
fi
39+
assertTestFailure TestRunner.elm
40+
# delete the failing tests and the comma on the preceding line
41+
ex -c 'g/should fail/' -c 'd' -c 'g-1' -c 's/,$//' -c 'wq' Tests.elm
42+
rm -Rf elm-stuff
43+
assertTestSuccess TestRunner.elm
1744
cd ..
1845
rm -Rf tmp
1946

20-
echo "$0: Testing examples..."
21-
cd examples
22-
elm-package install --yes
23-
elm-test Test.elm | tee test.log
24-
if test ${PIPESTATUS[0]} -ne 1; then
25-
echo "$0: ERROR: Expected example tests to fail" >&2
26-
exit 1
27-
fi
28-
cd ..
29-
3047
echo ""
3148
echo "$0: Everything looks good!"
3249
echo " "

0 commit comments

Comments
 (0)