Initial commit

master
Sven Slootweg 7 years ago
commit 7da080b8c3

2
.gitignore vendored

@ -0,0 +1,2 @@
/node_modules/
/lib/

@ -0,0 +1 @@
/node_modules/

@ -0,0 +1,29 @@
# drv
A Nix `.drv` file parser.
## License
[WTFPL](http://www.wtfpl.net/txt/copying/) or [CC0](https://creativecommons.org/publicdomain/zero/1.0/), whichever you prefer. A donation and/or attribution are appreciated, but not required.
## Donate
Maintaining open-source projects takes a lot of time, and the more donations I receive, the more time I can dedicate to open-source. If this module is useful to you, consider [making a donation](http://cryto.net/~joepie91/donate.html)!
You can donate using Bitcoin, PayPal, Flattr, cash-in-mail, SEPA transfers, and pretty much anything else. Thank you!
## Contributing
Pull requests welcome. Please make sure your modifications are in line with the overall code style, and ensure that you're editing the files in `src/`, not those in `lib/`.
Build tool of choice is `gulp`; simply run `gulp` while developing, and it will watch for changes.
Be aware that by making a pull request, you agree to release your modifications under the licenses stated above.
## Usage
TODO
## API
TODO

@ -0,0 +1,32 @@
const gulp = require('gulp');
const presetES2015 = require("@joepie91/gulp-preset-es2015");
const presetPegjs = require("@joepie91/gulp-preset-pegjs")
let sources = {
babel: ["src/**/*.js"],
pegjs: ["src/**/*.pegjs"]
}
gulp.task('babel', function() {
return gulp.src(sources.babel)
.pipe(presetES2015({
basePath: __dirname
}))
.pipe(gulp.dest("lib/"));
});
gulp.task('pegjs', function() {
return gulp.src(sources.pegjs)
.pipe(presetPegjs({
basePath: __dirname
}))
.pipe(gulp.dest("lib/"));
})
gulp.task('watch', function () {
gulp.watch(sources.babel, ['babel']);
gulp.watch(sources.pegjs, ['pegjs']);
});
gulp.task('default', ['pegjs', 'babel', 'watch']);

@ -0,0 +1,3 @@
'use strict';
module.exports = require("./lib");

@ -0,0 +1,29 @@
{
"name": "drv",
"version": "1.0.0",
"description": "Nix .drv file parser",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "http://git.cryto.net/joepie91/node-drv.git"
},
"keywords": [
"nix",
"nixos",
"drv",
"derive",
"derivation",
"parser"
],
"author": "Sven Slootweg",
"license": "WTFPL",
"devDependencies": {
"@joepie91/gulp-preset-es2015": "^1.0.1",
"@joepie91/gulp-preset-pegjs": "^1.0.0",
"babel-preset-es2015": "^6.6.0",
"gulp": "^3.9.1"
}
}

@ -0,0 +1,30 @@
start
= deriveTag
value
= deriveTag
/ array
/ tuple
/ string
multipleItems
= item:value subsequentItems:("," value)* { return [item].concat(subsequentItems.map(subsequentItem => subsequentItem[1])); }
deriveTag
= "Derive(" items:multipleItems ")" { return {type: "deriveTag", items: items}; }
array
= "[" items:multipleItems "]" { return {type: "array", items: items}; }
tuple
= "(" items:multipleItems ")" { return {type: "tuple", items: items}; }
string
= '"' chars:stringCharacter* '"' { return chars.join(""); }
stringCharacter
= !('"' / "\\") char:. { return char; }
/ stringEscapedQuote { return '"'; }
stringEscapedQuote
= '\\"'

@ -0,0 +1,84 @@
'use strict';
const drvParser = require("./drv");
function valueType(value) {
if (typeof value === "string") {
return "string";
} else {
return value.type;
}
}
function assertType(value, expectedType) {
if (valueType(value) == null) {
throw new Error(`Expected a '${expectedType}', got nothing`);
} else if (valueType(value) !== expectedType) {
throw new Error(`Expected a '${expectedType}', got '${valueType(value)}'`);
} else {
return true;
}
}
function assertedValue(type, value) {
if (assertType(value, type)) {
return value;
}
}
function mapArray(array, callback) {
return assertedValue("array", array).items.map(callback);
}
function mapTuple(tuple, fields, callback) {
return assertedValue("tuple", tuple).items.reduce((result, item, i) => {
if (fields[i] != null) {
let value;
if (callback != null) {
value = callback(item, i);
} else {
value = item;
}
result[fields[i]] = value;
return result;
} else {
throw new Error(`Attempted to map field ${i}, but only ${fields.length} field names were specified`);
}
}, {});
}
function parseDerivation(text) {
let root = parseAST(text);
return {
outputs: mapArray(root.items[0], (item) => {
return mapTuple(item, ["name", "path", "hashAlgorithm", "hash"]);
}),
inputDerivations: mapArray(root.items[1], (item) => {
return mapTuple(item, ["path", "inputDerivations"], (value, i) => {
if (i === 1) {
/* An `array` of inputDerivations */
return value.items;
} else {
return value;
}
});
}),
inputSources: assertedValue("array", root.items[2]).items,
platform: assertedValue("string", root.items[3]),
builder: assertedValue("string", root.items[4]),
builderArguments: assertedValue("array", root.items[5]).items,
environmentVariables: mapArray(root.items[6], (item) => {
return mapTuple(item, ["name", "value"]);
})
}
};
function parseAST(text) {
return drvParser.parse(text);
}
parseDerivation.ast = parseAST;
module.exports = parseDerivation;

@ -0,0 +1,12 @@
'use strict';
const util = require("util");
const parse = require("./lib");
let testDerivation = 'Derive([("dev","/nix/store/lpwm4gcsda53g26jp6rxz4x13l8lywzg-libXdmcp-1.1.2-dev","",""),("doc","/nix/store/y8925a01zwzrw0sakpv066bc4m6b2qj5-libXdmcp-1.1.2-doc","",""),("out","/nix/store/3iq0cd1ll0c7hss8xxgalxqn0jm0b2mi-libXdmcp-1.1.2","","")],[("/nix/store/3l3gnqvlwrmiqdma5vg3zibkabv4d6wh-pkg-config-0.29.drv",["out"]),("/nix/store/6qrlismj26hncj3809k302z6d3ycfwhh-stdenv.drv",["out"]),("/nix/store/flyb4cyxz0s48iq8qcdxdf2bcmgcc4cq-bash-4.3-p48.drv",["out"]),("/nix/store/pm59fc4bwblygsfxbq5dr72lkg7wxwsi-libXdmcp-1.1.2.tar.bz2.drv",["out"]),("/nix/store/w3qvvackybwaq6d2sw58yacsrbbrxa4b-xproto-7.0.29.drv",["out"])],["/nix/store/zsi9kk33hj7kvjfw0zahpdsiggg58nn4-builder.sh"],"x86_64-linux","/nix/store/gabjbkwga2dhhp2wzyaxl83r8hjjfc37-bash-4.3-p48/bin/bash",["-e","/nix/store/zsi9kk33hj7kvjfw0zahpdsiggg58nn4-builder.sh"],[("buildInputs",""),("builder","/nix/store/gabjbkwga2dhhp2wzyaxl83r8hjjfc37-bash-4.3-p48/bin/bash"),("dev","/nix/store/lpwm4gcsda53g26jp6rxz4x13l8lywzg-libXdmcp-1.1.2-dev"),("doc","/nix/store/y8925a01zwzrw0sakpv066bc4m6b2qj5-libXdmcp-1.1.2-doc"),("hardeningDisable","bindnow relro"),("name","libXdmcp-1.1.2"),("nativeBuildInputs","/nix/store/y419xb805psvlia6rl2jjrxmfsin5v63-pkg-config-0.29 /nix/store/cpy3mign235h3bjx63jz4baiislqznb9-xproto-7.0.29"),("out","/nix/store/3iq0cd1ll0c7hss8xxgalxqn0jm0b2mi-libXdmcp-1.1.2"),("outputs","out dev doc"),("propagatedBuildInputs",""),("propagatedNativeBuildInputs",""),("src","/nix/store/djf171kmvws6891q2nzd2icdjd5bgj4r-libXdmcp-1.1.2.tar.bz2"),("stdenv","/nix/store/985d95clq0216a6pcp3qzw4igp84ajvr-stdenv"),("system","x86_64-linux")])';
try {
console.log(util.inspect(parse(testDerivation), {colors: true, depth: null}));
} catch (err) {
console.error(util.inspect(err, {colors: true}));
}
Loading…
Cancel
Save