summaryrefslogtreecommitdiff
path: root/node_modules/jake/lib/publish_task.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/jake/lib/publish_task.js')
-rw-r--r--node_modules/jake/lib/publish_task.js290
1 files changed, 290 insertions, 0 deletions
diff --git a/node_modules/jake/lib/publish_task.js b/node_modules/jake/lib/publish_task.js
new file mode 100644
index 0000000..f0cacfd
--- /dev/null
+++ b/node_modules/jake/lib/publish_task.js
@@ -0,0 +1,290 @@
+/*
+ * Jake JavaScript build tool
+ * Copyright 2112 Matthew Eernisse (mde@fleegix.org)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+let fs = require('fs');
+let path = require('path');
+let exec = require('child_process').execSync;
+let FileList = require('filelist').FileList;
+
+let PublishTask = function () {
+ let args = Array.prototype.slice.call(arguments).filter(function (item) {
+ return typeof item != 'undefined';
+ });
+ let arg;
+ let opts = {};
+ let definition;
+ let prereqs = [];
+ let createDef = function (arg) {
+ return function () {
+ this.packageFiles.include(arg);
+ };
+ };
+
+ this.name = args.shift();
+
+ // Old API, just name + list of files
+ if (args.length == 1 && (Array.isArray(args[0]) || typeof args[0] == 'string')) {
+ definition = createDef(args.pop());
+ }
+ // Current API, name + [prereqs] + [opts] + definition
+ else {
+ while ((arg = args.pop())) {
+ // Definition func
+ if (typeof arg == 'function') {
+ definition = arg;
+ }
+ // Prereqs
+ else if (Array.isArray(arg) || typeof arg == 'string') {
+ prereqs = arg;
+ }
+ // Opts
+ else {
+ opts = arg;
+ }
+ }
+ }
+
+ this.prereqs = prereqs;
+ this.packageFiles = new FileList();
+ this.publishCmd = opts.publishCmd || 'npm publish %filename';
+ this.publishMessage = opts.publishMessage || 'BOOM! Published.';
+ this.gitCmd = opts.gitCmd || 'git';
+ this.versionFiles = opts.versionFiles || ['package.json'];
+ this.scheduleDelay = 5000;
+
+ // Override utility funcs for testing
+ this._ensureRepoClean = function (stdout) {
+ if (stdout.length) {
+ fail(new Error('Git repository is not clean.'));
+ }
+ };
+ this._getCurrentBranch = function (stdout) {
+ return String(stdout).trim();
+ };
+
+ if (typeof definition == 'function') {
+ definition.call(this);
+ }
+ this.define();
+};
+
+
+PublishTask.prototype = new (function () {
+
+ let _currentBranch = null;
+
+ let getPackage = function () {
+ let pkg = JSON.parse(fs.readFileSync(path.join(process.cwd(),
+ '/package.json')).toString());
+ return pkg;
+ };
+ let getPackageVersionNumber = function () {
+ return getPackage().version;
+ };
+
+ this.define = function () {
+ let self = this;
+
+ namespace('publish', function () {
+ task('fetchTags', function () {
+ // Make sure local tags are up to date
+ exec(self.gitCmd + ' fetch --tags');
+ console.log('Fetched remote tags.');
+ });
+
+ task('getCurrentBranch', function () {
+ // Figure out what branch to push to
+ let stdout = exec(self.gitCmd + ' symbolic-ref --short HEAD').toString();
+ if (!stdout) {
+ throw new Error('No current Git branch found');
+ }
+ _currentBranch = self._getCurrentBranch(stdout);
+ console.log('On branch ' + _currentBranch);
+ });
+
+ task('ensureClean', function () {
+ // Only bump, push, and tag if the Git repo is clean
+ let stdout = exec(self.gitCmd + ' status --porcelain --untracked-files=no').toString();
+ // Throw if there's output
+ self._ensureRepoClean(stdout);
+ });
+
+ task('updateVersionFiles', function () {
+ let pkg;
+ let version;
+ let arr;
+ let patch;
+
+ // Grab the current version-string
+ pkg = getPackage();
+ version = pkg.version;
+ // Increment the patch-number for the version
+ arr = version.split('.');
+ patch = parseInt(arr.pop(), 10) + 1;
+ arr.push(patch);
+ version = arr.join('.');
+
+ // Update package.json or other files with the new version-info
+ self.versionFiles.forEach(function (file) {
+ let p = path.join(process.cwd(), file);
+ let data = JSON.parse(fs.readFileSync(p).toString());
+ data.version = version;
+ fs.writeFileSync(p, JSON.stringify(data, true, 2) + '\n');
+ });
+ // Return the version string so that listeners for the 'complete' event
+ // for this task can use it (e.g., to update other files before pushing
+ // to Git)
+ return version;
+ });
+
+ task('pushVersion', ['ensureClean', 'updateVersionFiles'], function () {
+ let version = getPackageVersionNumber();
+ let message = 'Version ' + version;
+ let cmds = [
+ self.gitCmd + ' commit -a -m "' + message + '"',
+ self.gitCmd + ' push origin ' + _currentBranch,
+ self.gitCmd + ' tag -a v' + version + ' -m "' + message + '"',
+ self.gitCmd + ' push --tags'
+ ];
+ cmds.forEach((cmd) => {
+ exec(cmd);
+ });
+ version = getPackageVersionNumber();
+ console.log('Bumped version number to v' + version + '.');
+ });
+
+ let defineTask = task('definePackage', function () {
+ let version = getPackageVersionNumber();
+ new jake.PackageTask(self.name, 'v' + version, self.prereqs, function () {
+ // Replace the PackageTask's FileList with the PublishTask's FileList
+ this.packageFiles = self.packageFiles;
+ this.needTarGz = true; // Default to tar.gz
+ // If any of the need<CompressionFormat> or archive opts are set
+ // proxy them to the PackageTask
+ for (let p in this) {
+ if (p.indexOf('need') === 0 || p.indexOf('archive') === 0) {
+ if (typeof self[p] != 'undefined') {
+ this[p] = self[p];
+ }
+ }
+ }
+ });
+ });
+ defineTask._internal = true;
+
+ task('package', function () {
+ let definePack = jake.Task['publish:definePackage'];
+ let pack = jake.Task['package'];
+ let version = getPackageVersionNumber();
+
+ // May have already been run
+ if (definePack.taskStatus == jake.Task.runStatuses.DONE) {
+ definePack.reenable(true);
+ }
+ definePack.invoke();
+ // Set manually, completion happens in next tick, creating deadlock
+ definePack.taskStatus = jake.Task.runStatuses.DONE;
+ pack.invoke();
+ console.log('Created package for ' + self.name + ' v' + version);
+ });
+
+ task('publish', function () {
+ return new Promise((resolve) => {
+ let version = getPackageVersionNumber();
+ let filename;
+ let cmd;
+
+ console.log('Publishing ' + self.name + ' v' + version);
+
+ if (typeof self.createPublishCommand == 'function') {
+ cmd = self.createPublishCommand(version);
+ }
+ else {
+ filename = './pkg/' + self.name + '-v' + version + '.tar.gz';
+ cmd = self.publishCmd.replace(/%filename/gi, filename);
+ }
+
+ if (typeof cmd == 'function') {
+ cmd(function (err) {
+ if (err) {
+ throw err;
+ }
+ console.log(self.publishMessage);
+ resolve();
+ });
+ }
+ else {
+ // Hackity hack -- NPM publish sometimes returns errror like:
+ // Error sending version data\nnpm ERR!
+ // Error: forbidden 0.2.4 is modified, should match modified time
+ setTimeout(function () {
+ let stdout = exec(cmd).toString() || '';
+ stdout = stdout.trim();
+ if (stdout) {
+ console.log(stdout);
+ }
+ console.log(self.publishMessage);
+ resolve();
+ }, self.scheduleDelay);
+ }
+ });
+ });
+
+ task('cleanup', function () {
+ return new Promise((resolve) => {
+ let clobber = jake.Task.clobber;
+ clobber.reenable(true);
+ clobber.on('complete', function () {
+ console.log('Cleaned up package');
+ resolve();
+ });
+ clobber.invoke();
+ });
+ });
+
+ });
+
+ let prefixNs = function (item) {
+ return 'publish:' + item;
+ };
+
+ // Create aliases in the default namespace
+ desc('Create a new version and release.');
+ task('publish', self.prereqs.concat(['version', 'release']
+ .map(prefixNs)));
+
+ desc('Release the existing version.');
+ task('publishExisting', self.prereqs.concat(['release']
+ .map(prefixNs)));
+
+ task('version', ['fetchTags', 'getCurrentBranch', 'pushVersion']
+ .map(prefixNs));
+
+ task('release', ['package', 'publish', 'cleanup']
+ .map(prefixNs));
+
+ // Invoke proactively so there will be a callable 'package' task
+ // which can be used apart from 'publish'
+ jake.Task['publish:definePackage'].invoke();
+ };
+
+})();
+
+jake.PublishTask = PublishTask;
+exports.PublishTask = PublishTask;
+