Initial commit
commit
7da080b8c3
@ -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…
Reference in New Issue