diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..ccc6f09 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,19 @@ +{ + "plugins": [ "joyent" ], + "extends": [ + "eslint:recommended", + "plugin:joyent/style", + "plugin:joyent/lint" + ], + "parserOptions": { + "ecmaVersion": 5, + "sourceType": "script", + "ecmaFeatures": { + } + }, + "env": { + "node": true + }, + "rules": { + } +} diff --git a/.gitignore b/.gitignore index eb03e3e..5d407f3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ -node_modules +/build +/coverage +/node_modules *.log diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..6998f69 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "deps/jsstyle"] + path = deps/jsstyle + url = https://github.com/joyent/jsstyle.git diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..c0daf5f --- /dev/null +++ b/.npmignore @@ -0,0 +1,12 @@ +*.log +/Makefile +/deps +/test +/tools +/.gitmodules +/.npmignore +/.eslintrc +/.travis.yml +/CONTRIBUTING.md +/build +/coverage diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 09d3ef3..0000000 --- a/.travis.yml +++ /dev/null @@ -1,4 +0,0 @@ -language: node_js -node_js: - - 0.8 - - 0.10 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..c13e1a8 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,13 @@ +# Contributing + +This repository uses GitHub pull requests for code review. + +See the [Joyent Engineering +Guidelines](https://github.com/joyent/eng/blob/master/docs/index.md) for general +best practices expected in this repository. + +Contributions should be "make prepush" clean. The "prepush" target runs the +"check" target, which will check for linting and style errors. + +If you're changing something non-trivial or user-facing, you may want to submit +an issue first. diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..c84387d --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,65 @@ +@Library('jenkins-joylib@v1.0.3') _ + +pipeline { + + agent none + + options { + buildDiscarder(logRotator(numToKeepStr: '45')) + timestamps() + } + + stages { + stage('top') { + parallel { + stage('v4-zone') { + agent { + label joyCommonLabels(image_ver: '15.4.1') + } + tools { + nodejs 'sdcnode-v4-zone' + } + stages { + stage('check') { + steps{ + sh('make check') + } + } + stage('test') { + steps{ + sh('make test') + } + } + } + } + + stage('v6-zone64') { + agent { + label joyCommonLabels(image_ver: '18.4.0') + } + tools { + nodejs 'sdcnode-v6-zone64' + } + stages { + stage('check') { + steps{ + sh('make check') + } + } + stage('test') { + steps{ + sh('make test') + } + } + } + } + } + } + } + + post { + always { + joyMattermostNotification() + } + } +} diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b9a8bd5 --- /dev/null +++ b/Makefile @@ -0,0 +1,59 @@ +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# +# Copyright 2019, Joyent, Inc. +# + +# +# node-asn1 Makefile +# + +# +# Tools +# + +ISTANBUL := node_modules/.bin/istanbul +FAUCET := node_modules/.bin/faucet +NODE := node +NPM := npm + +# +# Files +# + +JS_FILES := $(shell find lib test -name '*.js') +JSSTYLE_FILES = $(JS_FILES) +JSSTYLE_FLAGS = -f tools/jsstyle.conf +ESLINT = ./node_modules/.bin/eslint +ESLINT_FILES = $(JS_FILES) + +include ./tools/mk/Makefile.defs +include ./tools/mk/Makefile.smf.defs + +# +# Repo-specific targets +# + +.PHONY: all +all: $(TAPE) + $(NPM) rebuild + +$(ISTANBUL): | $(NPM_EXEC) + $(NPM) install + +$(FAUCET): | $(NPM_EXEC) + $(NPM) install + +CLEAN_FILES += ./node_modules/ + +.PHONY: test +test: $(ISTANBUL) $(FAUCET) + $(ISTANBUL) cover --print none test/run.js | $(FAUCET) + +include ./tools/mk/Makefile.deps +include ./tools/mk/Makefile.smf.targ +include ./tools/mk/Makefile.targ diff --git a/README.md b/README.md index 7cebf7a..2208210 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ The following reads an ASN.1 sequence with a boolean. var Ber = require('asn1').Ber; - var reader = new Ber.Reader(new Buffer([0x30, 0x03, 0x01, 0x01, 0xff])); + var reader = new Ber.Reader(Buffer.from([0x30, 0x03, 0x01, 0x01, 0xff])); reader.readSequence(); console.log('Sequence len: ' + reader.length); @@ -47,4 +47,4 @@ MIT. ## Bugs -See . +See . diff --git a/deps/jsstyle b/deps/jsstyle new file mode 160000 index 0000000..52dc973 --- /dev/null +++ b/deps/jsstyle @@ -0,0 +1 @@ +Subproject commit 52dc973cf64da11834eca7cf46ebce8518e3ee88 diff --git a/lib/ber/errors.js b/lib/ber/errors.js index ff21d4f..4557b8a 100644 --- a/lib/ber/errors.js +++ b/lib/ber/errors.js @@ -3,7 +3,7 @@ module.exports = { - newInvalidAsn1Error: function(msg) { + newInvalidAsn1Error: function (msg) { var e = new Error(); e.name = 'InvalidAsn1Error'; e.message = msg || ''; diff --git a/lib/ber/index.js b/lib/ber/index.js index 4fb90ae..387d132 100644 --- a/lib/ber/index.js +++ b/lib/ber/index.js @@ -7,7 +7,7 @@ var Reader = require('./reader'); var Writer = require('./writer'); -///--- Exports +// --- Exports module.exports = { diff --git a/lib/ber/reader.js b/lib/ber/reader.js index 9745dc3..8a7e4ca 100644 --- a/lib/ber/reader.js +++ b/lib/ber/reader.js @@ -1,18 +1,19 @@ // Copyright 2011 Mark Cavage All rights reserved. var assert = require('assert'); +var Buffer = require('safer-buffer').Buffer; var ASN1 = require('./types'); var errors = require('./errors'); -///--- Globals +// --- Globals var newInvalidAsn1Error = errors.newInvalidAsn1Error; -///--- API +// --- API function Reader(data) { if (!data || !Buffer.isBuffer(data)) @@ -24,18 +25,26 @@ function Reader(data) { // These hold the "current" state this._len = 0; this._offset = 0; - - var self = this; - this.__defineGetter__('length', function() { return self._len; }); - this.__defineGetter__('offset', function() { return self._offset; }); - this.__defineGetter__('remain', function() { - return self._size - self._offset; - }); - this.__defineGetter__('buffer', function() { - return self._buf.slice(self._offset); - }); } +Object.defineProperty(Reader.prototype, 'length', { + enumerable: true, + get: function () { return (this._len); } +}); + +Object.defineProperty(Reader.prototype, 'offset', { + enumerable: true, + get: function () { return (this._offset); } +}); + +Object.defineProperty(Reader.prototype, 'remain', { + get: function () { return (this._size - this._offset); } +}); + +Object.defineProperty(Reader.prototype, 'buffer', { + get: function () { return (this._buf.slice(this._offset)); } +}); + /** * Reads a single byte and advances offset; you can pass in `true` to make this @@ -44,7 +53,7 @@ function Reader(data) { * @param {Boolean} peek true means don't move offset. * @return {Number} the next byte, null if not enough data. */ -Reader.prototype.readByte = function(peek) { +Reader.prototype.readByte = function (peek) { if (this._size - this._offset < 1) return null; @@ -57,7 +66,7 @@ Reader.prototype.readByte = function(peek) { }; -Reader.prototype.peek = function() { +Reader.prototype.peek = function () { return this.readByte(true); }; @@ -73,7 +82,7 @@ Reader.prototype.peek = function() { * @return {Number} the amount of offset to advance the buffer. * @throws {InvalidAsn1Error} on bad ASN.1 */ -Reader.prototype.readLength = function(offset) { +Reader.prototype.readLength = function (offset) { if (offset === undefined) offset = this._offset; @@ -84,10 +93,10 @@ Reader.prototype.readLength = function(offset) { if (lenB === null) return null; - if ((lenB & 0x80) == 0x80) { + if ((lenB & 0x80) === 0x80) { lenB &= 0x7f; - if (lenB == 0) + if (lenB === 0) throw newInvalidAsn1Error('Indefinite length not supported'); if (lenB > 4) @@ -116,7 +125,7 @@ Reader.prototype.readLength = function(offset) { * * @return {Number} the sequence's tag. */ -Reader.prototype.readSequence = function(tag) { +Reader.prototype.readSequence = function (tag) { var seq = this.peek(); if (seq === null) return null; @@ -133,22 +142,22 @@ Reader.prototype.readSequence = function(tag) { }; -Reader.prototype.readInt = function() { +Reader.prototype.readInt = function () { return this._readTag(ASN1.Integer); }; -Reader.prototype.readBoolean = function() { +Reader.prototype.readBoolean = function () { return (this._readTag(ASN1.Boolean) === 0 ? false : true); }; -Reader.prototype.readEnumeration = function() { +Reader.prototype.readEnumeration = function () { return this._readTag(ASN1.Enumeration); }; -Reader.prototype.readString = function(tag, retbuf) { +Reader.prototype.readString = function (tag, retbuf) { if (!tag) tag = ASN1.OctetString; @@ -171,7 +180,7 @@ Reader.prototype.readString = function(tag, retbuf) { this._offset = o; if (this.length === 0) - return ''; + return retbuf ? Buffer.alloc(0) : ''; var str = this._buf.slice(this._offset, this._offset + this.length); this._offset += this.length; @@ -179,7 +188,7 @@ Reader.prototype.readString = function(tag, retbuf) { return retbuf ? str : str.toString('utf8'); }; -Reader.prototype.readOID = function(tag) { +Reader.prototype.readOID = function (tag) { if (!tag) tag = ASN1.OID; @@ -195,7 +204,7 @@ Reader.prototype.readOID = function(tag) { value <<= 7; value += byte & 0x7f; - if ((byte & 0x80) == 0) { + if ((byte & 0x80) === 0) { values.push(value); value = 0; } @@ -209,7 +218,7 @@ Reader.prototype.readOID = function(tag) { }; -Reader.prototype._readTag = function(tag) { +Reader.prototype._readTag = function (tag) { assert.ok(tag !== undefined); var b = this.peek(); @@ -240,7 +249,7 @@ Reader.prototype._readTag = function(tag) { value |= (this._buf[this._offset++] & 0xff); } - if ((fb & 0x80) == 0x80 && i !== 4) + if ((fb & 0x80) === 0x80 && i !== 4) value -= (1 << (i * 8)); return value >> 0; @@ -248,6 +257,6 @@ Reader.prototype._readTag = function(tag) { -///--- Exported API +// --- Exported API module.exports = Reader; diff --git a/lib/ber/writer.js b/lib/ber/writer.js index 67b959b..368a9ef 100644 --- a/lib/ber/writer.js +++ b/lib/ber/writer.js @@ -1,11 +1,12 @@ // Copyright 2011 Mark Cavage All rights reserved. var assert = require('assert'); +var Buffer = require('safer-buffer').Buffer; var ASN1 = require('./types'); var errors = require('./errors'); -///--- Globals +// --- Globals var newInvalidAsn1Error = errors.newInvalidAsn1Error; @@ -15,16 +16,16 @@ var DEFAULT_OPTS = { }; -///--- Helpers +// --- Helpers function merge(from, to) { assert.ok(from); - assert.equal(typeof(from), 'object'); + assert.equal(typeof (from), 'object'); assert.ok(to); - assert.equal(typeof(to), 'object'); + assert.equal(typeof (to), 'object'); var keys = Object.getOwnPropertyNames(from); - keys.forEach(function(key) { + keys.forEach(function (key) { if (to[key]) return; @@ -37,12 +38,12 @@ function merge(from, to) { -///--- API +// --- API function Writer(options) { options = merge(DEFAULT_OPTS, options || {}); - this._buf = new Buffer(options.size || 1024); + this._buf = Buffer.alloc(options.size || 1024); this._size = this._buf.length; this._offset = 0; this._options = options; @@ -50,19 +51,19 @@ function Writer(options) { // A list of offsets in the buffer where we need to insert // sequence tag/len pairs. this._seq = []; - - var self = this; - this.__defineGetter__('buffer', function() { - if (self._seq.length) - throw new InvalidAsn1Error(self._seq.length + ' unended sequence(s)'); - - return self._buf.slice(0, self._offset); - }); } +Object.defineProperty(Writer.prototype, 'buffer', { + get: function () { + if (this._seq.length) + throw newInvalidAsn1Error(this._seq.length + ' unended sequence(s)'); + + return (this._buf.slice(0, this._offset)); + } +}); -Writer.prototype.writeByte = function(b) { - if (typeof(b) !== 'number') +Writer.prototype.writeByte = function (b) { + if (typeof (b) !== 'number') throw new TypeError('argument must be a Number'); this._ensure(1); @@ -70,22 +71,22 @@ Writer.prototype.writeByte = function(b) { }; -Writer.prototype.writeInt = function(i, tag) { - if (typeof(i) !== 'number') +Writer.prototype.writeInt = function (i, tag) { + if (typeof (i) !== 'number') throw new TypeError('argument must be a Number'); - if (typeof(tag) !== 'number') + if (typeof (tag) !== 'number') tag = ASN1.Integer; var sz = 4; while ((((i & 0xff800000) === 0) || ((i & 0xff800000) === 0xff800000 >> 0)) && - (sz > 1)) { + (sz > 1)) { sz--; i <<= 8; } if (sz > 4) - throw new InvalidAsn1Error('BER ints cannot be > 0xffffffff'); + throw newInvalidAsn1Error('BER ints cannot be > 0xffffffff'); this._ensure(2 + sz); this._buf[this._offset++] = tag; @@ -99,26 +100,26 @@ Writer.prototype.writeInt = function(i, tag) { }; -Writer.prototype.writeNull = function() { +Writer.prototype.writeNull = function () { this.writeByte(ASN1.Null); this.writeByte(0x00); }; -Writer.prototype.writeEnumeration = function(i, tag) { - if (typeof(i) !== 'number') +Writer.prototype.writeEnumeration = function (i, tag) { + if (typeof (i) !== 'number') throw new TypeError('argument must be a Number'); - if (typeof(tag) !== 'number') + if (typeof (tag) !== 'number') tag = ASN1.Enumeration; return this.writeInt(i, tag); }; -Writer.prototype.writeBoolean = function(b, tag) { - if (typeof(b) !== 'boolean') +Writer.prototype.writeBoolean = function (b, tag) { + if (typeof (b) !== 'boolean') throw new TypeError('argument must be a Boolean'); - if (typeof(tag) !== 'number') + if (typeof (tag) !== 'number') tag = ASN1.Boolean; this._ensure(3); @@ -128,10 +129,10 @@ Writer.prototype.writeBoolean = function(b, tag) { }; -Writer.prototype.writeString = function(s, tag) { - if (typeof(s) !== 'string') - throw new TypeError('argument must be a string (was: ' + typeof(s) + ')'); - if (typeof(tag) !== 'number') +Writer.prototype.writeString = function (s, tag) { + if (typeof (s) !== 'string') + throw new TypeError('argument must be a string (was: ' + typeof (s) + ')'); + if (typeof (tag) !== 'number') tag = ASN1.OctetString; var len = Buffer.byteLength(s); @@ -145,8 +146,8 @@ Writer.prototype.writeString = function(s, tag) { }; -Writer.prototype.writeBuffer = function(buf, tag) { - if (typeof(tag) !== 'number') +Writer.prototype.writeBuffer = function (buf, tag) { + if (typeof (tag) !== 'number') throw new TypeError('tag must be a number'); if (!Buffer.isBuffer(buf)) throw new TypeError('argument must be a buffer'); @@ -164,16 +165,16 @@ Writer.prototype.writeStringArray = function(strings) { throw new TypeError('argument must be an Array[String]'); var self = this; - strings.forEach(function(s) { + strings.forEach(function (s) { self.writeString(s); }); }; // This is really to solve DER cases, but whatever for now -Writer.prototype.writeOID = function(s, tag) { - if (typeof(s) !== 'string') +Writer.prototype.writeOID = function (s, tag) { + if (typeof (s) !== 'string') throw new TypeError('argument must be a string'); - if (typeof(tag) !== 'number') + if (typeof (tag) !== 'number') tag = ASN1.OID; if (!/^([0-9]+\.){3,}[0-9]+$/.test(s)) @@ -206,7 +207,7 @@ Writer.prototype.writeOID = function(s, tag) { var tmp = s.split('.'); var bytes = []; bytes.push(parseInt(tmp[0], 10) * 40 + parseInt(tmp[1], 10)); - tmp.slice(2).forEach(function(b) { + tmp.slice(2).forEach(function (b) { encodeOctet(bytes, parseInt(b, 10)); }); @@ -214,14 +215,14 @@ Writer.prototype.writeOID = function(s, tag) { this._ensure(2 + bytes.length); this.writeByte(tag); this.writeLength(bytes.length); - bytes.forEach(function(b) { + bytes.forEach(function (b) { self.writeByte(b); }); }; -Writer.prototype.writeLength = function(len) { - if (typeof(len) !== 'number') +Writer.prototype.writeLength = function (len) { + if (typeof (len) !== 'number') throw new TypeError('argument must be a Number'); this._ensure(4); @@ -241,12 +242,12 @@ Writer.prototype.writeLength = function(len) { this._buf[this._offset++] = len >> 8; this._buf[this._offset++] = len; } else { - throw new InvalidAsn1ERror('Length too long (> 4 bytes)'); + throw newInvalidAsn1Error('Length too long (> 4 bytes)'); } }; -Writer.prototype.startSequence = function(tag) { - if (typeof(tag) !== 'number') +Writer.prototype.startSequence = function (tag) { + if (typeof (tag) !== 'number') tag = ASN1.Sequence | ASN1.Constructor; this.writeByte(tag); @@ -256,7 +257,7 @@ Writer.prototype.startSequence = function(tag) { }; -Writer.prototype.endSequence = function() { +Writer.prototype.endSequence = function () { var seq = this._seq.pop(); var start = seq + 3; var len = this._offset - start; @@ -279,12 +280,12 @@ Writer.prototype.endSequence = function() { this._buf[seq + 2] = len >> 8; this._buf[seq + 3] = len; } else { - throw new InvalidAsn1Error('Sequence too long'); + throw newInvalidAsn1Error('Sequence too long'); } }; -Writer.prototype._shift = function(start, len, shift) { +Writer.prototype._shift = function (start, len, shift) { assert.ok(start !== undefined); assert.ok(len !== undefined); assert.ok(shift); @@ -293,7 +294,7 @@ Writer.prototype._shift = function(start, len, shift) { this._offset += shift; }; -Writer.prototype._ensure = function(len) { +Writer.prototype._ensure = function (len) { assert.ok(len); if (this._size - this._offset < len) { @@ -301,7 +302,7 @@ Writer.prototype._ensure = function(len) { if (sz - this._offset < len) sz += len; - var buf = new Buffer(sz); + var buf = Buffer.alloc(sz); this._buf.copy(buf, 0, 0, this._offset); this._buf = buf; @@ -311,6 +312,6 @@ Writer.prototype._ensure = function(len) { -///--- Exported API +// --- Exported API module.exports = Writer; diff --git a/lib/index.js b/lib/index.js index d1766e7..ede3ab2 100644 --- a/lib/index.js +++ b/lib/index.js @@ -7,7 +7,7 @@ var Ber = require('./ber/index'); -///--- Exported API +// --- Exported API module.exports = { diff --git a/package.json b/package.json index 0dcd627..2b51c75 100644 --- a/package.json +++ b/package.json @@ -1,22 +1,31 @@ { - "author": "Mark Cavage ", + "author": "Joyent (joyent.com)", "contributors": [ + "Mark Cavage ", "David Gwynne ", - "Yunong Xiao " + "Yunong Xiao ", + "Alex Wilson " ], "name": "asn1", "description": "Contains parsers and serializers for ASN.1 (currently BER only)", - "version": "0.2.1", + "version": "0.2.4", "repository": { "type": "git", - "url": "git://github.com/mcavage/node-asn1.git" + "url": "git://github.com/joyent/node-asn1.git" }, "main": "lib/index.js", - "dependencies": {}, + "dependencies": { + "safer-buffer": "~2.1.0" + }, "devDependencies": { - "tap": "0.4.8" + "istanbul": "^0.3.6", + "faucet": "0.0.1", + "tape": "^3.5.0", + "eslint": "2.13.1", + "eslint-plugin-joyent": "~1.3.0" }, "scripts": { - "test": "./node_modules/.bin/tap ./tst" - } + "test": "./node_modules/.bin/tape ./test/ber/*.test.js" + }, + "license": "MIT" } diff --git a/tst/ber/reader.test.js b/test/ber/reader.test.js similarity index 68% rename from tst/ber/reader.test.js rename to test/ber/reader.test.js index 062fd7e..95ac5a9 100644 --- a/tst/ber/reader.test.js +++ b/test/ber/reader.test.js @@ -1,22 +1,24 @@ // Copyright 2011 Mark Cavage All rights reserved. -var test = require('tap').test; +var test = require('tape'); +var Buffer = require('safer-buffer').Buffer; -///--- Globals +// --- Globals var BerReader; -///--- Tests +// --- Tests -test('load library', function(t) { +test('load library', function (t) { BerReader = require('../../lib/index').BerReader; t.ok(BerReader); try { - new BerReader(); + var reader = new BerReader(); + t.equal(reader, null, 'reader'); t.fail('Should have thrown'); } catch (e) { t.ok(e instanceof TypeError, 'Should have been a type error'); @@ -25,16 +27,16 @@ test('load library', function(t) { }); -test('read byte', function(t) { - var reader = new BerReader(new Buffer([0xde])); +test('read byte', function (t) { + var reader = new BerReader(Buffer.from([0xde])); t.ok(reader); t.equal(reader.readByte(), 0xde, 'wrong value'); t.end(); }); -test('read 1 byte int', function(t) { - var reader = new BerReader(new Buffer([0x02, 0x01, 0x03])); +test('read 1 byte int', function (t) { + var reader = new BerReader(Buffer.from([0x02, 0x01, 0x03])); t.ok(reader); t.equal(reader.readInt(), 0x03, 'wrong value'); t.equal(reader.length, 0x01, 'wrong length'); @@ -42,8 +44,8 @@ test('read 1 byte int', function(t) { }); -test('read 2 byte int', function(t) { - var reader = new BerReader(new Buffer([0x02, 0x02, 0x7e, 0xde])); +test('read 2 byte int', function (t) { + var reader = new BerReader(Buffer.from([0x02, 0x02, 0x7e, 0xde])); t.ok(reader); t.equal(reader.readInt(), 0x7ede, 'wrong value'); t.equal(reader.length, 0x02, 'wrong length'); @@ -51,8 +53,8 @@ test('read 2 byte int', function(t) { }); -test('read 3 byte int', function(t) { - var reader = new BerReader(new Buffer([0x02, 0x03, 0x7e, 0xde, 0x03])); +test('read 3 byte int', function (t) { + var reader = new BerReader(Buffer.from([0x02, 0x03, 0x7e, 0xde, 0x03])); t.ok(reader); t.equal(reader.readInt(), 0x7ede03, 'wrong value'); t.equal(reader.length, 0x03, 'wrong length'); @@ -60,8 +62,8 @@ test('read 3 byte int', function(t) { }); -test('read 4 byte int', function(t) { - var reader = new BerReader(new Buffer([0x02, 0x04, 0x7e, 0xde, 0x03, 0x01])); +test('read 4 byte int', function (t) { + var reader = new BerReader(Buffer.from([0x02, 0x04, 0x7e, 0xde, 0x03, 0x01])); t.ok(reader); t.equal(reader.readInt(), 0x7ede0301, 'wrong value'); t.equal(reader.length, 0x04, 'wrong length'); @@ -69,8 +71,8 @@ test('read 4 byte int', function(t) { }); -test('read 1 byte negative int', function(t) { - var reader = new BerReader(new Buffer([0x02, 0x01, 0xdc])); +test('read 1 byte negative int', function (t) { + var reader = new BerReader(Buffer.from([0x02, 0x01, 0xdc])); t.ok(reader); t.equal(reader.readInt(), -36, 'wrong value'); t.equal(reader.length, 0x01, 'wrong length'); @@ -78,8 +80,8 @@ test('read 1 byte negative int', function(t) { }); -test('read 2 byte negative int', function(t) { - var reader = new BerReader(new Buffer([0x02, 0x02, 0xc0, 0x4e])); +test('read 2 byte negative int', function (t) { + var reader = new BerReader(Buffer.from([0x02, 0x02, 0xc0, 0x4e])); t.ok(reader); t.equal(reader.readInt(), -16306, 'wrong value'); t.equal(reader.length, 0x02, 'wrong length'); @@ -87,8 +89,8 @@ test('read 2 byte negative int', function(t) { }); -test('read 3 byte negative int', function(t) { - var reader = new BerReader(new Buffer([0x02, 0x03, 0xff, 0x00, 0x19])); +test('read 3 byte negative int', function (t) { + var reader = new BerReader(Buffer.from([0x02, 0x03, 0xff, 0x00, 0x19])); t.ok(reader); t.equal(reader.readInt(), -65511, 'wrong value'); t.equal(reader.length, 0x03, 'wrong length'); @@ -96,8 +98,8 @@ test('read 3 byte negative int', function(t) { }); -test('read 4 byte negative int', function(t) { - var reader = new BerReader(new Buffer([0x02, 0x04, 0x91, 0x7c, 0x22, 0x1f])); +test('read 4 byte negative int', function (t) { + var reader = new BerReader(Buffer.from([0x02, 0x04, 0x91, 0x7c, 0x22, 0x1f])); t.ok(reader); t.equal(reader.readInt(), -1854135777, 'wrong value'); t.equal(reader.length, 0x04, 'wrong length'); @@ -105,8 +107,8 @@ test('read 4 byte negative int', function(t) { }); -test('read boolean true', function(t) { - var reader = new BerReader(new Buffer([0x01, 0x01, 0xff])); +test('read boolean true', function (t) { + var reader = new BerReader(Buffer.from([0x01, 0x01, 0xff])); t.ok(reader); t.equal(reader.readBoolean(), true, 'wrong value'); t.equal(reader.length, 0x01, 'wrong length'); @@ -114,8 +116,8 @@ test('read boolean true', function(t) { }); -test('read boolean false', function(t) { - var reader = new BerReader(new Buffer([0x01, 0x01, 0x00])); +test('read boolean false', function (t) { + var reader = new BerReader(Buffer.from([0x01, 0x01, 0x00])); t.ok(reader); t.equal(reader.readBoolean(), false, 'wrong value'); t.equal(reader.length, 0x01, 'wrong length'); @@ -123,8 +125,8 @@ test('read boolean false', function(t) { }); -test('read enumeration', function(t) { - var reader = new BerReader(new Buffer([0x0a, 0x01, 0x20])); +test('read enumeration', function (t) { + var reader = new BerReader(Buffer.from([0x0a, 0x01, 0x20])); t.ok(reader); t.equal(reader.readEnumeration(), 0x20, 'wrong value'); t.equal(reader.length, 0x01, 'wrong length'); @@ -132,9 +134,9 @@ test('read enumeration', function(t) { }); -test('read string', function(t) { +test('read string', function (t) { var dn = 'cn=foo,ou=unit,o=test'; - var buf = new Buffer(dn.length + 2); + var buf = Buffer.alloc(dn.length + 2); buf[0] = 0x04; buf[1] = Buffer.byteLength(dn); buf.write(dn, 2); @@ -146,8 +148,8 @@ test('read string', function(t) { }); -test('read sequence', function(t) { - var reader = new BerReader(new Buffer([0x30, 0x03, 0x01, 0x01, 0xff])); +test('read sequence', function (t) { + var reader = new BerReader(Buffer.from([0x30, 0x03, 0x01, 0x01, 0xff])); t.ok(reader); t.equal(reader.readSequence(), 0x30, 'wrong value'); t.equal(reader.length, 0x03, 'wrong length'); @@ -157,8 +159,8 @@ test('read sequence', function(t) { }); -test('anonymous LDAPv3 bind', function(t) { - var BIND = new Buffer(14); +test('anonymous LDAPv3 bind', function (t) { + var BIND = Buffer.alloc(14); BIND[0] = 0x30; // Sequence BIND[1] = 12; // len BIND[2] = 0x02; // ASN.1 Integer @@ -191,9 +193,8 @@ test('anonymous LDAPv3 bind', function(t) { }); -test('long string', function(t) { - var buf = new Buffer(256); - var o; +test('long string', function (t) { + var buf = Buffer.alloc(256); var s = '2;649;CN=Red Hat CS 71GA Demo,O=Red Hat CS 71GA Demo,C=US;' + 'CN=RHCS Agent - admin01,UID=admin01,O=redhat,C=US [1] This is ' + diff --git a/tst/ber/writer.test.js b/test/ber/writer.test.js similarity index 88% rename from tst/ber/writer.test.js rename to test/ber/writer.test.js index d87cb7b..17c4671 100644 --- a/tst/ber/writer.test.js +++ b/test/ber/writer.test.js @@ -1,18 +1,17 @@ // Copyright 2011 Mark Cavage All rights reserved. -var test = require('tap').test; -var sys = require('sys'); +var test = require('tape'); +var Buffer = require('safer-buffer').Buffer; -///--- Globals +// --- Globals var BerWriter; -var BerReader; -///--- Tests +// --- Tests -test('load library', function(t) { +test('load library', function (t) { BerWriter = require('../../lib/index').BerWriter; t.ok(BerWriter); t.ok(new BerWriter()); @@ -20,7 +19,7 @@ test('load library', function(t) { }); -test('write byte', function(t) { +test('write byte', function (t) { var writer = new BerWriter(); writer.writeByte(0xC2); @@ -34,7 +33,7 @@ test('write byte', function(t) { }); -test('write 1 byte int', function(t) { +test('write 1 byte int', function (t) { var writer = new BerWriter(); writer.writeInt(0x7f); @@ -50,7 +49,7 @@ test('write 1 byte int', function(t) { }); -test('write 2 byte int', function(t) { +test('write 2 byte int', function (t) { var writer = new BerWriter(); writer.writeInt(0x7ffe); @@ -67,7 +66,7 @@ test('write 2 byte int', function(t) { }); -test('write 3 byte int', function(t) { +test('write 3 byte int', function (t) { var writer = new BerWriter(); writer.writeInt(0x7ffffe); @@ -85,7 +84,7 @@ test('write 3 byte int', function(t) { }); -test('write 4 byte int', function(t) { +test('write 4 byte int', function (t) { var writer = new BerWriter(); writer.writeInt(0x7ffffffe); @@ -105,7 +104,7 @@ test('write 4 byte int', function(t) { }); -test('write 1 byte negative int', function(t) { +test('write 1 byte negative int', function (t) { var writer = new BerWriter(); writer.writeInt(-128); @@ -122,7 +121,7 @@ test('write 1 byte negative int', function(t) { }); -test('write 2 byte negative int', function(t) { +test('write 2 byte negative int', function (t) { var writer = new BerWriter(); writer.writeInt(-22400); @@ -140,7 +139,7 @@ test('write 2 byte negative int', function(t) { }); -test('write 3 byte negative int', function(t) { +test('write 3 byte negative int', function (t) { var writer = new BerWriter(); writer.writeInt(-481653); @@ -159,7 +158,7 @@ test('write 3 byte negative int', function(t) { }); -test('write 4 byte negative int', function(t) { +test('write 4 byte negative int', function (t) { var writer = new BerWriter(); writer.writeInt(-1522904131); @@ -179,7 +178,7 @@ test('write 4 byte negative int', function(t) { }); -test('write boolean', function(t) { +test('write boolean', function (t) { var writer = new BerWriter(); writer.writeBoolean(true); @@ -199,7 +198,7 @@ test('write boolean', function(t) { }); -test('write string', function(t) { +test('write string', function (t) { var writer = new BerWriter(); writer.writeString('hello world'); var ber = writer.buffer; @@ -213,13 +212,13 @@ test('write string', function(t) { t.end(); }); -test('write buffer', function(t) { +test('write buffer', function (t) { var writer = new BerWriter(); // write some stuff to start with writer.writeString('hello world'); var ber = writer.buffer; - var buf = new Buffer([0x04, 0x0b, 0x30, 0x09, 0x02, 0x01, 0x0f, 0x01, 0x01, - 0xff, 0x01, 0x01, 0xff]); + var buf = Buffer.from([0x04, 0x0b, 0x30, 0x09, 0x02, 0x01, 0x0f, 0x01, 0x01, + 0xff, 0x01, 0x01, 0xff]); writer.writeBuffer(buf.slice(2, buf.length), 0x04); ber = writer.buffer; @@ -236,7 +235,7 @@ test('write buffer', function(t) { t.end(); }); -test('write string array', function(t) { +test('write string array', function (t) { var writer = new BerWriter(); writer.writeStringArray(['hello world', 'fubar!']); var ber = writer.buffer; @@ -256,7 +255,7 @@ test('write string array', function(t) { }); -test('resize internal buffer', function(t) { +test('resize internal buffer', function (t) { var writer = new BerWriter({size: 2}); writer.writeString('hello world'); var ber = writer.buffer; @@ -271,7 +270,7 @@ test('resize internal buffer', function(t) { }); -test('sequence', function(t) { +test('sequence', function (t) { var writer = new BerWriter({size: 25}); writer.startSequence(); writer.writeString('hello world'); @@ -291,7 +290,7 @@ test('sequence', function(t) { }); -test('nested sequence', function(t) { +test('nested sequence', function (t) { var writer = new BerWriter({size: 25}); writer.startSequence(); writer.writeString('hello world'); @@ -318,7 +317,7 @@ test('nested sequence', function(t) { }); -test('LDAP bind message', function(t) { +test('LDAP bind message', function (t) { var dn = 'cn=foo,ou=unit,o=test'; var writer = new BerWriter(); writer.startSequence(); @@ -354,7 +353,7 @@ test('LDAP bind message', function(t) { }); -test('Write OID', function(t) { +test('Write OID', function (t) { var oid = '1.2.840.113549.1.1.1'; var writer = new BerWriter(); writer.writeOID(oid); @@ -362,7 +361,7 @@ test('Write OID', function(t) { var ber = writer.buffer; t.ok(ber); console.log(require('util').inspect(ber)); - console.log(require('util').inspect(new Buffer([0x06, 0x09, 0x2a, 0x86, + console.log(require('util').inspect(Buffer.from([0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01]))); diff --git a/test/run.js b/test/run.js new file mode 100644 index 0000000..5e7e80e --- /dev/null +++ b/test/run.js @@ -0,0 +1,16 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/* + * Copyright (c) 2018, Joyent, Inc. + */ + +'use strict'; + +// --- Run All Tests + +require('./ber/reader.test.js'); +require('./ber/writer.test.js'); diff --git a/tools/jsstyle.conf b/tools/jsstyle.conf new file mode 100644 index 0000000..6f09704 --- /dev/null +++ b/tools/jsstyle.conf @@ -0,0 +1,14 @@ +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# +# Copyright (c) 2018, Joyent, Inc. +# + +indent=2 +doxygen +unparenthesized-return=0 +strict-indent=true diff --git a/tools/mk/Makefile.defs b/tools/mk/Makefile.defs new file mode 100644 index 0000000..73dd612 --- /dev/null +++ b/tools/mk/Makefile.defs @@ -0,0 +1,105 @@ +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# +# Copyright (c) 2018, Joyent, Inc. +# + +# +# Makefile.defs: common defines. +# +# NOTE: This makefile comes from the "eng" repo. It's designed to be dropped +# into other repos as-is without requiring any modifications. If you find +# yourself changing this file, you should instead update the original copy in +# eng.git and then update your repo to use the new version. +# +# This makefile defines some useful defines. Include it at the top of +# your Makefile. +# +# Definitions in this Makefile: +# +# TOP The absolute path to the project directory. The top dir. +# BRANCH The current git branch. +# TIMESTAMP The timestamp for the build. This can be set via +# the TIMESTAMP envvar (used by MG-based builds). +# STAMP A build stamp to use in built package names. +# +# MAKE_STAMPS_DIR The directory in which make stamp files are to be +# created. See comments below on expensive targets. +# +# CACHE_DIR A directory tree in which temporary files may be +# collected by download, tarball extraction, etc. This +# directory is completely removed by "make distclean". +# Files in this directory are not intended to be shipped. +# + +TOP := $(shell pwd) + +# +# Mountain Gorilla-spec'd versioning. +# See "Package Versioning" in MG's README.md: +# +# +# Need GNU awk for multi-char arg to "-F". +_AWK := $(shell (which gawk >/dev/null && echo gawk) \ + || (which nawk >/dev/null && echo nawk) \ + || echo awk) +BRANCH := $(shell git symbolic-ref HEAD | $(_AWK) -F/ '{print $$3}') +ifeq ($(TIMESTAMP),) + TIMESTAMP := $(shell date -u "+%Y%m%dT%H%M%SZ") +endif +_GITDESCRIBE := g$(shell git describe --all --long --dirty | $(_AWK) -F'-g' '{print $$NF}') +STAMP := $(BRANCH)-$(TIMESTAMP)-$(_GITDESCRIBE) + +# node-gyp will print build info useful for debugging with V=1 +export V=1 + +CACHE_DIR ?= cache +DISTCLEAN_FILES += $(CACHE_DIR) + +# +# EXPENSIVE TARGETS AND MAKE STAMP FILES +# +# Targets which are expensive to run and lack a single file that marks +# completion are difficult to track with make; e.g., "npm install". One +# solution to this problem is to create "stamp" files with symbolic names which +# are created as the final step in a complex make rule in order to mark +# completion. +# +# In order to make these more uniform, and easier to target with "make clean", +# we will attempt to store them under a single directory. Note that these +# files are never targets for shipping in build artefacts. +# +# Stamp-backed targets come in several parts. First, a macro should be defined +# which names a file in the MAKE_STAMPS_DIR directory. Then, a target which +# creates this stamp file must be provided. The recipe for this target should +# use MAKE_STAMP_REMOVE and MAKE_STAMP_CREATE to perform the appropriate stamp +# management. +# +# For example: +# +# --- Makefile.*.defs: +# +# $(STAMP_EXPENSIVE_RESULT) := $(MAKE_STAMPS_DIR)/expensive-result +# +# --- Makefile.*.targ: +# +# $(STAMP_EXPENSIVE_RESULT): input/file another/input/file +# $(MAKE_STAMP_REMOVE) +# rm -rf output_tree/ # <--- ensure a clean slate +# expensive_program -o output_tree/ $^ +# $(MAKE_STAMP_CREATE) +# +# NOTE: Every stamp file is exposed as an implicit "stamp-$STAMP_NAME" target. +# The example above could be built manually by invoking: +# +# make stamp-expensive-result +# +MAKE_STAMPS_DIR ?= make_stamps +CLEAN_FILES += $(MAKE_STAMPS_DIR) + +MAKE_STAMP_REMOVE = mkdir -p $(@D); rm -f $(@) +MAKE_STAMP_CREATE = mkdir -p $(@D); touch $(@) diff --git a/tools/mk/Makefile.deps b/tools/mk/Makefile.deps new file mode 100644 index 0000000..91f8346 --- /dev/null +++ b/tools/mk/Makefile.deps @@ -0,0 +1,87 @@ +# -*- mode: makefile -*- +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# +# Copyright (c) 2017, Joyent, Inc. +# + +# +# Makefile.deps: Makefile for including common tools as dependencies +# +# NOTE: This makefile comes from the "eng" repo. It's designed to be dropped +# into other repos as-is without requiring any modifications. If you find +# yourself changing this file, you should instead update the original copy in +# eng.git and then update your repo to use the new version. +# +# This file is separate from Makefile.targ so that teams can choose +# independently whether to use the common targets in Makefile.targ and the +# common tools here. +# + +# +# javascriptlint +# +JSL_EXEC ?= deps/javascriptlint/build/install/jsl +JSL ?= $(JSL_EXEC) + +$(JSL_EXEC): | deps/javascriptlint/.git + cd deps/javascriptlint && make install + +distclean:: + if [[ -f deps/javascriptlint/Makefile ]]; then \ + cd deps/javascriptlint && make clean; \ + fi + +# +# jsstyle +# +JSSTYLE_EXEC ?= deps/jsstyle/jsstyle +JSSTYLE ?= $(JSSTYLE_EXEC) + +$(JSSTYLE_EXEC): | deps/jsstyle/.git + +# +# eslint +# +ESLINT_EXEC ?= node_modules/.bin/eslint +ifdef NODE + ESLINT := $(NODE) $(ESLINT_EXEC) +else + ESLINT ?= $(ESLINT_EXEC) +endif + +# Install eslint. +# +# The install of specific modules is to allow running "make check" +# without having to do a complete install of all npm dependencies. +# +# NPM_EXEC will be defined if either of "Makefile.{node,node_prebuilt}.defs" +# is included. +ifdef NPM +$(ESLINT_EXEC): package.json | $(NPM_EXEC) + ESLINT_VER=$$($(NODE) -e 'console.log(require("./package.json").devDependencies["eslint"] || "")') && \ + ESLINT_JOY_VER=$$($(NODE) -e 'console.log(require("./package.json").devDependencies["eslint-plugin-joyent"] || "")') && \ + [[ -n $$ESLINT_VER && -n $$ESLINT_JOY_VER ]] && \ + $(NPM) install --no-save eslint@$$ESLINT_VER eslint-plugin-joyent@$$ESLINT_JOY_VER && \ + touch $(ESLINT_EXEC) +else +$(ESLINT_EXEC): package.json + ESLINT_VER=$$(node -e 'console.log(require("./package.json").devDependencies["eslint"] || "")') && \ + ESLINT_JOY_VER=$$(node -e 'console.log(require("./package.json").devDependencies["eslint-plugin-joyent"] || "")') && \ + [[ -n $$ESLINT_VER && -n $$ESLINT_JOY_VER ]] && \ + npm install --no-save eslint@$$ESLINT_VER eslint-plugin-joyent@$$ESLINT_JOY_VER && \ + touch $(ESLINT_EXEC) +endif + +# +# restdown +# +RESTDOWN_EXEC ?= deps/restdown/bin/restdown +RESTDOWN ?= python $(RESTDOWN_EXEC) +$(RESTDOWN_EXEC): | deps/restdown/.git + +EXTRA_DOC_DEPS ?= diff --git a/tools/mk/Makefile.node.defs b/tools/mk/Makefile.node.defs new file mode 100644 index 0000000..487824d --- /dev/null +++ b/tools/mk/Makefile.node.defs @@ -0,0 +1,110 @@ +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# +# Copyright (c) 2017, Joyent, Inc. +# + +# +# Makefile.node.defs: Makefile for building and bundling your own Node.js. +# +# NOTE: This makefile comes from the "eng" repo. It's designed to be dropped +# into other repos as-is without requiring any modifications. If you find +# yourself changing this file, you should instead update the original copy in +# eng.git and then update your repo to use the new version. +# + +# +# This Makefile facilitates building and bundling your own copy of Node.js in +# your repo. All it does is define variables for node, node-waf, and npm for +# you to use elsewhere in your Makefile and rules to build these tools when +# needed. +# +# To use this facility, include "Makefile.node.defs", use the variables as +# described below to define targets, and then include "Makefile.node.targ". +# +# There are two use cases addressed here: +# +# (1) Invoking node, node-waf, or npm as part of the build process, as in "npm +# install" and "node-waf configure build". To facilitate this, this +# Makefile defines Make variables NODE, NODE_WAF, and NPM that you can use +# to invoke these commands during the build process. You MUST NOT assume +# that these variables just evaluate to the filenames themselves, as they +# may have environment variable definitions and other things that prevent +# you from using them directly as a filename. If you want that, see (2). +# +# Wherever you use one of these variables, you MUST include a dependency on +# the corresponding *_EXEC variable as well, like so: +# +# node_modules/restify: deps/restify $(NPM_EXEC) +# $(NPM) install deps/restify +# +# or better, use an order-only dependency to avoid spurious rebuilds: +# +# node_modules/restify: deps/restify | $(NPM_EXEC) +# $(NPM) install deps/restify +# +# Otherwise, the underlying file will not get built. We don't +# automatically build them as part of "all" because that approach is +# brittle. +# +# (2) Specifying paths for invoking node, node-waf, or npm at RUNTIME, as in +# specifying the path to node used for the start method of your service's +# SMF manifest. For this, this Makefile defines variables NODE_EXEC, +# NODE_WAF_EXEC, and NPM_EXEC, which represent the relative paths of these +# files from the root of the workspace. You MUST NOT use these variables +# to invoke these commands during the build process. See (1) instead. +# +# However, in order to work at runtime, you must build the tool as well. +# That is, if you use NODE_EXEC to specify the path to node, you must +# depend on NODE_EXEC somewhere. This usually happens anyway because you +# usually need them during the build process too, but if you don't then +# you need to explicitly add NODE_EXEC (or whichever) to your "all" +# target. +# +# When including this Makefile, you MAY also specify: +# +# BUILD top-level directory for built binaries +# (default: "build") +# +# NODE_INSTALL where node should install its built items +# (default: "$BUILD/node") +# +# NODE_CONFIG_FLAGS extra flags to pass to Node's "configure" +# (default: "--with-dtrace" on SmartOS; empty +# otherwise.) +# + +TOP ?= $(error You must include Makefile.defs before this makefile) + +BUILD ?= build +NODE_INSTALL ?= $(BUILD)/node +DISTCLEAN_FILES += $(NODE_INSTALL) + +NODE_CONFIG_FLAGS += --prefix=$(TOP)/$(NODE_INSTALL) + +ifeq ($(shell uname -s),SunOS) + NODE_CONFIG_FLAGS += --with-dtrace \ + --openssl-libpath=/opt/local/lib \ + --openssl-includes=/opt/local/include +endif + +NODE_EXEC = $(NODE_INSTALL)/bin/node +NODE_WAF_EXEC = $(NODE_INSTALL)/bin/node-waf +NPM_EXEC = $(NODE_INSTALL)/bin/npm + +# +# These paths should be used during the build process to invoke Node and +# Node-related build tools like NPM. All paths are fully qualified so that +# they work regardless of the current working directory at the point of +# invocation. +# +# Note that where PATH is overridden, the value chosen must cause execution of +# "node" to find the same binary to which the NODE macro refers. +# +NODE := $(TOP)/$(NODE_EXEC) +NODE_WAF := $(TOP)/$(NODE_WAF_EXEC) +NPM := PATH=$(TOP)/$(NODE_INSTALL)/bin:$(PATH) $(NODE) $(TOP)/$(NPM_EXEC) diff --git a/tools/mk/Makefile.node.targ b/tools/mk/Makefile.node.targ new file mode 100644 index 0000000..bf53f78 --- /dev/null +++ b/tools/mk/Makefile.node.targ @@ -0,0 +1,42 @@ +# -*- mode: makefile -*- +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# +# Copyright (c) 2014, Joyent, Inc. +# + +# +# Makefile.node.targ: See Makefile.node.defs. +# +# NOTE: This makefile comes from the "eng" repo. It's designed to be dropped +# into other repos as-is without requiring any modifications. If you find +# yourself changing this file, you should instead update the original copy in +# eng.git and then update your repo to use the new version. +# + +ifneq ($(shell uname -s),SunOS) +NODE_PREBUILT_VERSION ?= $(error You must define NODE_PREBUILT_VERSION to use Makefile.node.targ on non-SunOS) +endif + +ifeq ($(shell uname -s),SunOS) +$(NODE_EXEC) $(NPM_EXEC) $(NODE_WAF_EXEC): | deps/node/.git + (cd deps/node; ./configure $(NODE_CONFIG_FLAGS) && $(MAKE) && $(MAKE) install) +else +$(NODE_EXEC) $(NPM_EXEC) $(NODE_WAF_EXEC): + (mkdir -p $(BUILD) \ + && cd $(BUILD) \ + && [[ -d src-node ]] && (cd src-node && git checkout master && git pull) || git clone https://github.com/joyent/node.git src-node \ + && cd src-node \ + && git checkout $(NODE_PREBUILT_VERSION) \ + && ./configure $(NODE_CONFIG_FLAGS) \ + && $(MAKE) && $(MAKE) install) +endif + +DISTCLEAN_FILES += $(NODE_INSTALL) $(BUILD)/src-node + +distclean:: + -([[ ! -d deps/node ]] || (cd deps/node && $(MAKE) distclean)) diff --git a/tools/mk/Makefile.node_deps.defs b/tools/mk/Makefile.node_deps.defs new file mode 100644 index 0000000..29a83f7 --- /dev/null +++ b/tools/mk/Makefile.node_deps.defs @@ -0,0 +1,43 @@ +# -*- mode: makefile -*- +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# +# Copyright (c) 2014, Joyent, Inc. +# + +# +# Makefile.node_deps.defs: Makefile for including npm modules whose sources +# reside inside the repo. This should NOT be used for modules in the npm +# public repo or modules that could be specified with git SHAs. +# +# NOTE: This makefile comes from the "eng" repo. It's designed to be dropped +# into other repos as-is without requiring any modifications. If you find +# yourself changing this file, you should instead update the original copy in +# eng.git and then update your repo to use the new version. +# + +# +# This Makefile takes as input the following make variable: +# +# REPO_MODULES List of relative paths to node modules (i.e., npm +# packages) inside this repo. For example: +# src/node-canative, where there's a binary npm package +# in src/node-canative. +# +# Based on the above, this Makefile defines the following new variables: +# +# REPO_DEPS List of relative paths to the installed modules. For +# example: "node_modules/canative". +# +# The accompanying Makefile.node_deps.targ defines a target that will install +# each of REPO_MODULES into REPO_DEPS and remove REPO_DEPS with "make clean". +# The top-level Makefile is responsible for depending on REPO_DEPS where +# appropriate (usually the "deps" or "all" target). +# + +REPO_DEPS = $(REPO_MODULES:src/node-%=node_modules/%) +CLEAN_FILES += $(REPO_DEPS) diff --git a/tools/mk/Makefile.node_deps.targ b/tools/mk/Makefile.node_deps.targ new file mode 100644 index 0000000..bb2ab4f --- /dev/null +++ b/tools/mk/Makefile.node_deps.targ @@ -0,0 +1,24 @@ +# -*- mode: makefile -*- +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# +# Copyright (c) 2014, Joyent, Inc. +# + +# +# Makefile.node_deps.targ: targets for Makefile.node_deps.defs. +# +# NOTE: This makefile comes from the "eng" repo. It's designed to be dropped +# into other repos as-is without requiring any modifications. If you find +# yourself changing this file, you should instead update the original copy in +# eng.git and then update your repo to use the new version. +# + +NPM_EXEC ?= $(error NPM_EXEC must be defined for Makefile.node_deps.targ) + +node_modules/%: src/node-% | $(NPM_EXEC) + $(NPM) install $< diff --git a/tools/mk/Makefile.node_prebuilt.defs b/tools/mk/Makefile.node_prebuilt.defs new file mode 100644 index 0000000..2129742 --- /dev/null +++ b/tools/mk/Makefile.node_prebuilt.defs @@ -0,0 +1,159 @@ +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# +# Copyright (c) 2017, Joyent, Inc. +# + +# +# Makefile.node_prebuilt.defs: Makefile for including a prebuilt Node.js build. +# +# NOTE: This makefile comes from the "eng" repo. It's designed to be dropped +# into other repos as-is without requiring any modifications. If you find +# yourself changing this file, you should instead update the original copy in +# eng.git and then update your repo to use the new version. +# + +# +# This Makefile facilitates downloading and bundling a prebuilt node.js +# build (using the 'sdcnode' distro builds). This is an alternative to +# the "Makefile.node.*" makefiles for *building* a node from source. +# +# Usage: +# +# - Define `NODE_PREBUILT_VERSION` in your Makefile to choose a node version. +# E.g.: `NODE_PREBUILT_VERSION=v0.6.19`. See other optional variables +# below. +# - `include tools/mk/Makefile.node_prebuilt.defs` after this in your Makefile. +# - `include tools/mk/Makefile.node_prebuilt.targ` near the end of your +# Makefile. +# - Have at least one of your Makefile targets depend on either `$(NODE_EXEC)` +# or `$(NPM_EXEC)`. E.g.: +# +# node_modules/restify: deps/restify $(NPM_EXEC) +# $(NPM) install deps/restify +# +# or better, use an order-only dependency to avoid spurious rebuilds: +# +# node_modules/restify: deps/restify | $(NPM_EXEC) +# $(NPM) install deps/restify +# +# - Use `$(NPM)` or `$(NODE)` to use your node build. +# - Include the "$(NODE_INSTALL)" tree in your release package. +# +# +# When including this Makefile, you MUST also specify: +# +# NODE_PREBUILT_VERSION The node version in the prebuilt 'sdcnode' +# package to use. Typically this is one of the +# node version tags, e.g. "v0.6.18" but it +# can be any commitish. +# +# When including this Makefile, you MAY also specify: +# +# NODE_PREBUILT_DIR The dir in which to find sdcnode builds. This +# can either be a *local directory* or *a +# URL* dir (with trailing '/') which serves +# Apache/Nginx dir listing HTML. +# (default: sdcnode master build dir on stuff) +# +# NODE_PREBUILT_TAG The 'sdcnode' project supports special +# configuration builds of node, e.g. say a +# build configured `--without-ssl`. These +# special configurations are given a tag, e.g. +# 'gz', that is used in the filename. Optionally +# specify a tag name here. +# (default: empty) +# +# NODE_PREBUILT_BRANCH Specify a particular branch of 'sdcnode' builds +# from which to pull. Generally one should stick +# with the default. +# (default: master) +# +# NODE_PREBUILT_IMAGE If you have a zone image that differs from that +# for an sdcnode build that you want to use (potential compat +# issues be damned), then set this to the UUID of the sdcnode +# build you want. See here for available build image uuids: +# +# +# BUILD top-level directory for built binaries +# (default: "build") +# +# NODE_INSTALL where node should install its built items +# (default: "$BUILD/node") +# +# +# Dev Notes: +# +# This works by getting "NODE_PREBUILT_NAME" from the provided "NODE_PREBUILT_*" +# vars and the image version (via 'mdata-get sdc:image_uuid'). The image uuid is +# included to ensure an exact match with the build machine. This name (e.g. +# "v0.6.18-zone-$uuid") is used to find a matching "sdcnode-$name-*.tgz" build +# in "NODE_PREBUILT_DIR" (either a local directory or a URL). That tarball is +# downloaded and extracted into "NODE_INSTALL". +# +# The "*_EXEC" vars are set to named symlinks, e.g. +# "build/prebuilt-node-v0.6.18-$uuid", so that a change of selected node +# build (say the developer changes NODE_PREBUILT_VERSION) will recreate the +# node install. +# +# See for details on 'sdcnode-*' +# package naming. +# + +TOP ?= $(error You must include Makefile.defs before this makefile) +NODE_PREBUILT_VERSION ?= $(error NODE_PREBUILT_VERSION is not set.) + + +BUILD ?= build +NODE_INSTALL ?= $(BUILD)/node +DISTCLEAN_FILES += $(NODE_INSTALL) \ + $(BUILD)/prebuilt-node-* $(BUILD)/prebuilt-npm-* + +NODE_PREBUILT_BRANCH ?= master +NODE_PREBUILT_IMAGE ?= $(shell pfexec mdata-get sdc:image_uuid) +ifeq ($(NODE_PREBUILT_TAG),) + NODE_PREBUILT_NAME := $(NODE_PREBUILT_VERSION)-$(NODE_PREBUILT_IMAGE) +else + NODE_PREBUILT_NAME := $(NODE_PREBUILT_VERSION)-$(NODE_PREBUILT_TAG)-$(NODE_PREBUILT_IMAGE) +endif +NODE_PREBUILT_PATTERN := sdcnode-$(NODE_PREBUILT_NAME)-$(NODE_PREBUILT_BRANCH)-.*\.tgz +NODE_PREBUILT_DIR ?= https://download.joyent.com/pub/build/sdcnode/$(NODE_PREBUILT_IMAGE)/$(NODE_PREBUILT_BRANCH)-latest/sdcnode/ +ifeq ($(shell echo $(NODE_PREBUILT_DIR) | cut -c 1-4),http) + NODE_PREBUILT_BASE := $(shell curl -ksS --fail --connect-timeout 30 $(NODE_PREBUILT_DIR) | grep 'href=' | cut -d'"' -f2 | grep "^$(NODE_PREBUILT_PATTERN)$$" | sort | tail -1) + ifneq ($(NODE_PREBUILT_BASE),) + NODE_PREBUILT_TARBALL := $(NODE_PREBUILT_DIR)$(NODE_PREBUILT_BASE) + endif +else + NODE_PREBUILT_BASE := $(shell ls -1 $(NODE_PREBUILT_DIR)/ | grep "^$(NODE_PREBUILT_PATTERN)$$" 2>/dev/null | sort | tail -1) + ifneq ($(NODE_PREBUILT_BASE),) + NODE_PREBUILT_TARBALL := $(NODE_PREBUILT_DIR)/$(NODE_PREBUILT_BASE) + endif +endif +ifeq ($(NODE_PREBUILT_TARBALL),) + NODE_PREBUILT_TARBALL = $(error NODE_PREBUILT_TARBALL is empty: no '$(NODE_PREBUILT_DIR)/$(NODE_PREBUILT_PATTERN)' found) +endif + + +# Prebuild-specific paths for the "*_EXEC" vars to ensure that +# a prebuild change (e.g. if master Makefile's NODE_PREBUILT_VERSION +# choice changes) causes a install of the new node. +NODE_EXEC := $(BUILD)/prebuilt-node-$(NODE_PREBUILT_NAME) +NODE_WAF_EXEC := $(BUILD)/prebuilt-node-waf-$(NODE_PREBUILT_NAME) +NPM_EXEC := $(BUILD)/prebuilt-npm-$(NODE_PREBUILT_NAME) + +# +# These paths should be used during the build process to invoke Node and +# Node-related build tools like NPM. All paths are fully qualified so that +# they work regardless of the current working directory at the point of +# invocation. +# +# Note that where PATH is overridden, the value chosen must cause execution of +# "node" to find the same binary to which the NODE macro refers. +# +NODE := $(TOP)/$(NODE_INSTALL)/bin/node +NODE_WAF := $(TOP)/$(NODE_INSTALL)/bin/node-waf +NPM := PATH=$(TOP)/$(NODE_INSTALL)/bin:$(PATH) $(NODE) $(TOP)/$(NODE_INSTALL)/bin/npm diff --git a/tools/mk/Makefile.node_prebuilt.targ b/tools/mk/Makefile.node_prebuilt.targ new file mode 100644 index 0000000..6877333 --- /dev/null +++ b/tools/mk/Makefile.node_prebuilt.targ @@ -0,0 +1,42 @@ +# -*- mode: makefile -*- +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# +# Copyright (c) 2014, Joyent, Inc. +# + +# +# Makefile.node_prebuilt.targ: Makefile for including a prebuilt Node.js +# build. +# +# NOTE: This makefile comes from the "eng" repo. It's designed to be dropped +# into other repos as-is without requiring any modifications. If you find +# yourself changing this file, you should instead update the original copy in +# eng.git and then update your repo to use the new version. + + +NODE_PREBUILT_TARBALL ?= $(error NODE_PREBUILT_TARBALL is not set: was Makefile.node_prebuilt.defs included?) + + +# TODO: remove this limitation +# Limitation: currently presuming that the NODE_INSTALL basename is +# 'node' and that sdcnode tarballs have a 'node' top-level dir. +$(NODE_EXEC) $(NPM_EXEC) $(NODE_WAF_EXEC): + [[ $(shell basename $(NODE_INSTALL)) == "node" ]] \ + || (echo "Limitation: 'basename NODE_INSTALL' is not 'node'" && exit 1) + rm -rf $(NODE_INSTALL) \ + $(BUILD)/prebuilt-node-* $(BUILD)/prebuilt-npm-* + mkdir -p $(shell dirname $(NODE_INSTALL)) + if [[ $(shell echo $(NODE_PREBUILT_TARBALL) | cut -c 1-4) == "http" ]]; then \ + echo "Downloading '$(NODE_PREBUILT_BASE)'."; \ + curl -ksS --fail --connect-timeout 30 -o $(shell dirname $(NODE_INSTALL))/$(NODE_PREBUILT_BASE) $(NODE_PREBUILT_TARBALL); \ + (cd $(shell dirname $(NODE_INSTALL)) && $(TAR) xf $(NODE_PREBUILT_BASE)); \ + else \ + (cd $(shell dirname $(NODE_INSTALL)) && $(TAR) xf $(NODE_PREBUILT_TARBALL)); \ + fi + ln -s $(TOP)/$(NODE_INSTALL)/bin/node $(NODE_EXEC) + ln -s $(TOP)/$(NODE_INSTALL)/bin/npm $(NPM_EXEC) diff --git a/tools/mk/Makefile.smf.defs b/tools/mk/Makefile.smf.defs new file mode 100644 index 0000000..b988bbe --- /dev/null +++ b/tools/mk/Makefile.smf.defs @@ -0,0 +1,40 @@ +# -*- mode: makefile -*- +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# +# Copyright (c) 2014, Joyent, Inc. +# + +# +# Makefile.smf.defs: common targets for SMF manifests +# +# NOTE: This makefile comes from the "eng" repo. It's designed to be dropped +# into other repos as-is without requiring any modifications. If you find +# yourself changing this file, you should instead update the original copy in +# eng.git and then update your repo to use the new version. +# +# This Makefile uses the following definitions: +# +# SMF_MANIFESTS_IN Source files for SMF manifests. The following +# substitutions will be made on these files: +# +# @@NODE@@ path to installed node +# +# It updates SMF_MANIFESTS with the set of files generated by SMF_MANIFESTS_IN. +# It also updates the "check" target to check the XML syntax of all manifests, +# generated or otherwise. +# +# To use this file, be sure to also include Makefile.smf.targ after defining +# targets. +# + +SED ?= sed +SMF_DTD ?= tools/service_bundle.dtd.1 +XMLLINT ?= xmllint --noout + +SMF_MANIFESTS += $(SMF_MANIFESTS_IN:%.in=%) +CLEAN_FILES += $(SMF_MANIFESTS_IN:%.in=%) diff --git a/tools/mk/Makefile.smf.targ b/tools/mk/Makefile.smf.targ new file mode 100644 index 0000000..f78de96 --- /dev/null +++ b/tools/mk/Makefile.smf.targ @@ -0,0 +1,29 @@ +# -*- mode: makefile -*- +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# +# Copyright (c) 2014, Joyent, Inc. +# + +# +# Makefile.smf.targ: see Makefile.smf.defs. +# +# NOTE: This makefile comes from the "eng" repo. It's designed to be dropped +# into other repos as-is without requiring any modifications. If you find +# yourself changing this file, you should instead update the original copy in +# eng.git and then update your repo to use the new version. +# +.PHONY: check-manifests +check-manifests: $(SMF_MANIFESTS:%=%.smfchk) + +%.smfchk: % + $(XMLLINT) --path $(dir $(SMF_DTD)) --dtdvalid $(SMF_DTD) $^ + +check:: check-manifests + +$(SMF_MANIFESTS): %: %.in + $(SED) -e 's#@@NODE@@#@@PREFIX@@/$(NODE_INSTALL)/bin/node#' $< > $@ diff --git a/tools/mk/Makefile.targ b/tools/mk/Makefile.targ new file mode 100644 index 0000000..dac448a --- /dev/null +++ b/tools/mk/Makefile.targ @@ -0,0 +1,345 @@ +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# +# Copyright (c) 2017, Joyent, Inc. +# + +# +# Makefile.targ: common targets. +# +# NOTE: This makefile comes from the "eng" repo. It's designed to be dropped +# into other repos as-is without requiring any modifications. If you find +# yourself changing this file, you should instead update the original copy in +# eng.git and then update your repo to use the new version. +# +# This Makefile defines several useful targets and rules. You can use it by +# including it from a Makefile that specifies some of the variables below. +# +# Targets defined in this Makefile: +# +# check Checks JavaScript files for lint and style +# Checks bash scripts for syntax +# Checks SMF manifests for validity against the SMF DTD +# +# clean Removes built files +# +# docs Builds restdown documentation in docs/ +# +# prepush Depends on "check" and "test" +# +# test Does nothing (you should override this) +# +# xref Generates cscope (source cross-reference index) +# +# For details on what these targets are supposed to do, see the Joyent +# Engineering Guide. +# +# To make use of these targets, you'll need to set some of these variables. Any +# variables left unset will simply not be used. +# +# BASH_FILES Bash scripts to check for syntax +# (paths relative to top-level Makefile) +# +# CLEAN_FILES Files to remove as part of the "clean" target. Note +# that files generated by targets in this Makefile are +# automatically included in CLEAN_FILES. These include +# restdown-generated HTML and JSON files. +# +# DOC_FILES Restdown (documentation source) files. These are +# assumed to be contained in "docs/", and must NOT +# contain the "docs/" prefix. +# +# JSL_CONF_NODE Specify JavaScriptLint configuration files +# JSL_CONF_WEB (paths relative to top-level Makefile) +# +# Node.js and Web configuration files are separate +# because you'll usually want different global variable +# configurations. If no file is specified, none is given +# to jsl, which causes it to use a default configuration, +# which probably isn't what you want. +# +# JSL_FILES_NODE JavaScript files to check with Node config file. +# JSL_FILES_WEB JavaScript files to check with Web config file. +# +# JSON_FILES JSON files to be validated +# +# JSSTYLE_FILES JavaScript files to be style-checked +# +# You can also override these variables: +# +# BASH Path to bash (default: "bash") +# +# CSCOPE_DIRS Directories to search for source files for the cscope +# index. (default: ".") +# +# ESLINT Path to eslint (default: "eslint") +# +# ESLINT_FLAGS Additional flags to pass through to eslint +# +# JSL Path to JavaScriptLint (default: "jsl") +# +# JSL_FLAGS_NODE Additional flags to pass through to JSL +# JSL_FLAGS_WEB +# JSL_FLAGS +# +# JSON Path to json tool (default: "json") +# +# JSSTYLE Path to jsstyle (default: "jsstyle") +# +# JSSTYLE_FLAGS Additional flags to pass through to jsstyle +# +# RESTDOWN_EXT By default '.md' is required for DOC_FILES (see above). +# If you want to use, say, '.restdown' instead, then set +# 'RESTDOWN_EXT=.restdown' in your Makefile. +# + +# +# Defaults for the various tools we use. +# +BASH ?= bash +BASHSTYLE ?= $(NODE) tools/bashstyle +CP ?= cp +CSCOPE ?= cscope +CSCOPE_DIRS ?= . +ESLINT ?= eslint +JSL ?= jsl +JSON ?= json +JSSTYLE ?= jsstyle +MKDIR ?= mkdir -p +MV ?= mv +RESTDOWN_FLAGS ?= +RESTDOWN_EXT ?= .md +RMTREE ?= rm -rf +JSL_FLAGS ?= --nologo --nosummary + +ifeq ($(shell uname -s),SunOS) + TAR ?= gtar +else + TAR ?= tar +endif + + +# +# Defaults for other fixed values. +# +BUILD = build +DISTCLEAN_FILES += $(BUILD) +DOC_BUILD = $(BUILD)/docs/public + +# +# Configure JSL_FLAGS_{NODE,WEB} based on JSL_CONF_{NODE,WEB}. +# +ifneq ($(origin JSL_CONF_NODE), undefined) + JSL_FLAGS_NODE += --conf=$(JSL_CONF_NODE) +endif + +ifneq ($(origin JSL_CONF_WEB), undefined) + JSL_FLAGS_WEB += --conf=$(JSL_CONF_WEB) +endif + +# +# Targets. For descriptions on what these are supposed to do, see the +# Joyent Engineering Guide. +# + +# +# Instruct make to keep around temporary files. We have rules below that +# automatically update git submodules as needed, but they employ a deps/*/.git +# temporary file. Without this directive, make tries to remove these .git +# directories after the build has completed. +# +.SECONDARY: $($(wildcard deps/*):%=%/.git) + +# +# This rule enables other rules that use files from a git submodule to have +# those files depend on deps/module/.git and have "make" automatically check +# out the submodule as needed. +# +deps/%/.git: + git submodule update --init deps/$* + +# +# These recipes make heavy use of dynamically-created phony targets. The parent +# Makefile defines a list of input files like BASH_FILES. We then say that each +# of these files depends on a fake target called filename.bashchk, and then we +# define a pattern rule for those targets that runs bash in check-syntax-only +# mode. This mechanism has the nice properties that if you specify zero files, +# the rule becomes a noop (unlike a single rule to check all bash files, which +# would invoke bash with zero files), and you can check individual files from +# the command line with "make filename.bashchk". +# +.PHONY: check-bash +check-bash: $(BASH_FILES:%=%.bashchk) $(BASH_FILES:%=%.bashstyle) + +%.bashchk: % + $(BASH) -n $^ + +%.bashstyle: % + $(BASHSTYLE) $^ + +.PHONY: check-json +check-json: $(JSON_FILES:%=%.jsonchk) + +%.jsonchk: % + $(JSON) --validate -f $^ + +# +# The above approach can be slow when there are many files to check because it +# requires that "make" invoke the check tool once for each file, rather than +# passing in several files at once. For the JavaScript check targets, we define +# a variable for the target itself *only if* the list of input files is +# non-empty. This avoids invoking the tool if there are no files to check. +# + +ESLINT_TARGET = $(if $(ESLINT_FILES), check-eslint) +.PHONY: check-eslint +check-eslint: $(ESLINT_EXEC) + $(ESLINT) $(ESLINT_FLAGS) $(ESLINT_FILES) + +JSL_NODE_TARGET = $(if $(JSL_FILES_NODE), check-jsl-node) +.PHONY: check-jsl-node +check-jsl-node: $(JSL_EXEC) + $(JSL) $(JSL_FLAGS) $(JSL_FLAGS_NODE) $(JSL_FILES_NODE) + +JSL_WEB_TARGET = $(if $(JSL_FILES_WEB), check-jsl-web) +.PHONY: check-jsl-web +check-jsl-web: $(JSL_EXEC) + $(JSL) $(JSL_FLAGS) $(JSL_FLAGS_WEB) $(JSL_FILES_WEB) + +.PHONY: check-jsl +check-jsl: $(JSL_NODE_TARGET) $(JSL_WEB_TARGET) + +JSSTYLE_TARGET = $(if $(JSSTYLE_FILES), check-jsstyle) +.PHONY: check-jsstyle +check-jsstyle: $(JSSTYLE_EXEC) + $(JSSTYLE) $(JSSTYLE_FLAGS) $(JSSTYLE_FILES) + +.PHONY: check +check:: $(ESLINT_TARGET) check-jsl check-json $(JSSTYLE_TARGET) check-bash + @echo check ok + +.PHONY: clean +clean:: + -$(RMTREE) $(CLEAN_FILES) + +.PHONY: distclean +distclean:: clean + -$(RMTREE) $(DISTCLEAN_FILES) + +CSCOPE_FILES = cscope.in.out cscope.out cscope.po.out +CLEAN_FILES += $(CSCOPE_FILES) + +.PHONY: xref +xref: cscope.files + $(CSCOPE) -bqR + +.PHONY: cscope.files +cscope.files: + find $(CSCOPE_DIRS) -name '*.c' -o -name '*.h' -o -name '*.cc' \ + -o -name '*.js' -o -name '*.s' -o -name '*.cpp' > $@ + +# +# The "docs" target is complicated because we do several things here: +# +# (1) Use restdown to build HTML and JSON files from each of DOC_FILES. +# +# (2) Copy these files into $(DOC_BUILD) (build/docs/public), which +# functions as a complete copy of the documentation that could be +# mirrored or served over HTTP. +# +# (3) Then copy any directories and media from docs/media into +# $(DOC_BUILD)/media. This allows projects to include their own media, +# including files that will override same-named files provided by +# restdown. +# +# Step (3) is the surprisingly complex part: in order to do this, we need to +# identify the subdirectories in docs/media, recreate them in +# $(DOC_BUILD)/media, then do the same with the files. +# +DOC_MEDIA_DIRS := $(shell find docs/media -type d 2>/dev/null | grep -v "^docs/media$$") +DOC_MEDIA_DIRS := $(DOC_MEDIA_DIRS:docs/media/%=%) +DOC_MEDIA_DIRS_BUILD := $(DOC_MEDIA_DIRS:%=$(DOC_BUILD)/media/%) + +DOC_MEDIA_FILES := $(shell find docs/media -type f 2>/dev/null) +DOC_MEDIA_FILES := $(DOC_MEDIA_FILES:docs/media/%=%) +DOC_MEDIA_FILES_BUILD := $(DOC_MEDIA_FILES:%=$(DOC_BUILD)/media/%) + +# +# Like the other targets, "docs" just depends on the final files we want to +# create in $(DOC_BUILD), leveraging other targets and recipes to define how +# to get there. +# +.PHONY: docs +docs:: \ + $(DOC_FILES:%$(RESTDOWN_EXT)=$(DOC_BUILD)/%.html) \ + $(DOC_FILES:%$(RESTDOWN_EXT)=$(DOC_BUILD)/%.json) \ + $(DOC_MEDIA_FILES_BUILD) + +# +# We keep the intermediate files so that the next build can see whether the +# files in DOC_BUILD are up to date. +# +.PRECIOUS: \ + $(DOC_FILES:%$(RESTDOWN_EXT)=docs/%.html) \ + $(DOC_FILES:%$(RESTDOWN_EXT)=docs/%json) + +# +# We do clean those intermediate files, as well as all of DOC_BUILD. +# +CLEAN_FILES += \ + $(DOC_BUILD) \ + $(DOC_FILES:%$(RESTDOWN_EXT)=docs/%.html) \ + $(DOC_FILES:%$(RESTDOWN_EXT)=docs/%.json) + +# +# Before installing the files, we must make sure the directories exist. The | +# syntax tells make that the dependency need only exist, not be up to date. +# Otherwise, it might try to rebuild spuriously because the directory itself +# appears out of date. +# +$(DOC_MEDIA_FILES_BUILD): | $(DOC_MEDIA_DIRS_BUILD) + +$(DOC_BUILD)/%: docs/% | $(DOC_BUILD) + $(MKDIR) $(shell dirname $@) + $(CP) $< $@ + +docs/%.json docs/%.html: docs/%$(RESTDOWN_EXT) | $(DOC_BUILD) $(RESTDOWN_EXEC) \ + $(EXTRA_DOC_DEPS) + $(RESTDOWN) $(RESTDOWN_FLAGS) -m $(DOC_BUILD) $< + +$(DOC_BUILD): + $(MKDIR) $@ + +$(DOC_MEDIA_DIRS_BUILD): + $(MKDIR) $@ + +# +# The default "test" target does nothing. This should usually be overridden by +# the parent Makefile. It's included here so we can define "prepush" without +# requiring the repo to define "test". +# +.PHONY: test +test: + +.PHONY: prepush +prepush: check test + +# +# This rule automatically exposes every "stamp" file as a target that can be +# invoked manually as "stamp-$STAMP_NAME". For example, if a stamp has been +# defined thus: +# +# STAMP_EXPENSIVE_RESULT := $(MAKE_STAMPS_DIR)/expensive-result +# +# ... this can be invoked manually as "make stamp-expensive-result". Note that +# these phony targets are essentially just for interactive usage. Targets +# should be specified to depend on the macro containing the stamp file name. +# +# See also the comments in "Makefile.defs". +# +stamp-%: $(MAKE_STAMPS_DIR)/% + @: