[Service] Integrate DeviceHome and SignalingServer
[platform/framework/web/wrtjs.git] / device_home / node_modules / jake / lib / publish_task.js
1 /*
2  * Jake JavaScript build tool
3  * Copyright 2112 Matthew Eernisse (mde@fleegix.org)
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17 */
18
19 let fs = require('fs');
20 let path = require('path');
21 let exec = require('child_process').execSync;
22 let FileList = require('filelist').FileList;
23
24 let PublishTask = function () {
25   let args = Array.prototype.slice.call(arguments).filter(function (item) {
26     return typeof item != 'undefined';
27   });
28   let arg;
29   let opts = {};
30   let definition;
31   let prereqs = [];
32   let createDef = function (arg) {
33     return function () {
34       this.packageFiles.include(arg);
35     };
36   };
37
38   this.name = args.shift();
39
40   // Old API, just name + list of files
41   if (args.length == 1 && (Array.isArray(args[0]) || typeof args[0] == 'string')) {
42     definition = createDef(args.pop());
43   }
44   // Current API, name + [prereqs] + [opts] + definition
45   else {
46     while ((arg = args.pop())) {
47       // Definition func
48       if (typeof arg == 'function') {
49         definition = arg;
50       }
51       // Prereqs
52       else if (Array.isArray(arg) || typeof arg == 'string') {
53         prereqs = arg;
54       }
55       // Opts
56       else {
57         opts = arg;
58       }
59     }
60   }
61
62   this.prereqs = prereqs;
63   this.packageFiles = new FileList();
64   this.publishCmd = opts.publishCmd || 'npm publish %filename';
65   this.publishMessage = opts.publishMessage || 'BOOM! Published.';
66   this.gitCmd = opts.gitCmd || 'git';
67   this.versionFiles = opts.versionFiles || ['package.json'];
68   this.scheduleDelay = 5000;
69
70   // Override utility funcs for testing
71   this._ensureRepoClean = function (stdout) {
72     if (stdout.length) {
73       fail(new Error('Git repository is not clean.'));
74     }
75   };
76   this._getCurrentBranch = function (stdout) {
77     return String(stdout).trim();
78   };
79
80   if (typeof definition == 'function') {
81     definition.call(this);
82   }
83   this.define();
84 };
85
86
87 PublishTask.prototype = new (function () {
88
89   let _currentBranch = null;
90
91   let getPackage = function () {
92     let pkg = JSON.parse(fs.readFileSync(path.join(process.cwd(),
93       '/package.json')).toString());
94     return pkg;
95   };
96   let getPackageVersionNumber = function () {
97     return getPackage().version;
98   };
99
100   this.define = function () {
101     let self = this;
102
103     namespace('publish', function () {
104       task('fetchTags', function () {
105         // Make sure local tags are up to date
106         exec(self.gitCmd + ' fetch --tags');
107         console.log('Fetched remote tags.');
108       });
109
110       task('getCurrentBranch', function () {
111         // Figure out what branch to push to
112         let stdout = exec(self.gitCmd + ' symbolic-ref --short HEAD').toString();
113         if (!stdout) {
114           throw new Error('No current Git branch found');
115         }
116         _currentBranch = self._getCurrentBranch(stdout);
117         console.log('On branch ' + _currentBranch);
118       });
119
120       task('ensureClean', function () {
121         // Only bump, push, and tag if the Git repo is clean
122         let stdout = exec(self.gitCmd + ' status --porcelain --untracked-files=no').toString();
123         // Throw if there's output
124         self._ensureRepoClean(stdout);
125       });
126
127       task('updateVersionFiles', function () {
128         let pkg;
129         let version;
130         let arr;
131         let patch;
132
133         // Grab the current version-string
134         pkg = getPackage();
135         version = pkg.version;
136         // Increment the patch-number for the version
137         arr = version.split('.');
138         patch = parseInt(arr.pop(), 10) + 1;
139         arr.push(patch);
140         version = arr.join('.');
141
142         // Update package.json or other files with the new version-info
143         self.versionFiles.forEach(function (file) {
144           let p = path.join(process.cwd(), file);
145           let data = JSON.parse(fs.readFileSync(p).toString());
146           data.version = version;
147           fs.writeFileSync(p, JSON.stringify(data, true, 2) + '\n');
148         });
149         // Return the version string so that listeners for the 'complete' event
150         // for this task can use it (e.g., to update other files before pushing
151         // to Git)
152         return version;
153       });
154
155       task('pushVersion', ['ensureClean', 'updateVersionFiles'], function () {
156         let version = getPackageVersionNumber();
157         let message = 'Version ' + version;
158         let cmds = [
159           self.gitCmd + ' commit -a -m "' + message + '"',
160           self.gitCmd + ' push origin ' + _currentBranch,
161           self.gitCmd + ' tag -a v' + version + ' -m "' + message + '"',
162           self.gitCmd + ' push --tags'
163         ];
164         cmds.forEach((cmd) => {
165           exec(cmd);
166         });
167         version = getPackageVersionNumber();
168         console.log('Bumped version number to v' + version + '.');
169       });
170
171       let defineTask = task('definePackage', function () {
172         let version = getPackageVersionNumber();
173         new jake.PackageTask(self.name, 'v' + version, self.prereqs, function () {
174           // Replace the PackageTask's FileList with the PublishTask's FileList
175           this.packageFiles = self.packageFiles;
176           this.needTarGz = true; // Default to tar.gz
177           // If any of the need<CompressionFormat> or archive opts are set
178           // proxy them to the PackageTask
179           for (let p in this) {
180             if (p.indexOf('need') === 0 || p.indexOf('archive') === 0) {
181               if (typeof self[p] != 'undefined') {
182                 this[p] = self[p];
183               }
184             }
185           }
186         });
187       });
188       defineTask._internal = true;
189
190       task('package', function () {
191         let definePack = jake.Task['publish:definePackage'];
192         let pack = jake.Task['package'];
193         let version = getPackageVersionNumber();
194
195         // May have already been run
196         if (definePack.taskStatus == jake.Task.runStatuses.DONE) {
197           definePack.reenable(true);
198         }
199         definePack.invoke();
200         // Set manually, completion happens in next tick, creating deadlock
201         definePack.taskStatus = jake.Task.runStatuses.DONE;
202         pack.invoke();
203         console.log('Created package for ' + self.name + ' v' + version);
204       });
205
206       task('publish', function () {
207         return new Promise((resolve) => {
208           let version = getPackageVersionNumber();
209           let filename;
210           let cmd;
211
212           console.log('Publishing ' + self.name + ' v' + version);
213
214           if (typeof self.createPublishCommand == 'function') {
215             cmd = self.createPublishCommand(version);
216           }
217           else {
218             filename = './pkg/' + self.name + '-v' + version + '.tar.gz';
219             cmd = self.publishCmd.replace(/%filename/gi, filename);
220           }
221
222           if (typeof cmd == 'function') {
223             cmd(function (err) {
224               if (err) {
225                 throw err;
226               }
227               console.log(self.publishMessage);
228               resolve();
229             });
230           }
231           else {
232             // Hackity hack -- NPM publish sometimes returns errror like:
233             // Error sending version data\nnpm ERR!
234             // Error: forbidden 0.2.4 is modified, should match modified time
235             setTimeout(function () {
236               let stdout = exec(cmd).toString() || '';
237               stdout = stdout.trim();
238               if (stdout) {
239                 console.log(stdout);
240               }
241               console.log(self.publishMessage);
242               resolve();
243             }, self.scheduleDelay);
244           }
245         });
246       });
247
248       task('cleanup', function () {
249         return new Promise((resolve) => {
250           let clobber = jake.Task.clobber;
251           clobber.reenable(true);
252           clobber.on('complete', function () {
253             console.log('Cleaned up package');
254             resolve();
255           });
256           clobber.invoke();
257         });
258       });
259
260     });
261
262     let prefixNs = function (item) {
263       return 'publish:' + item;
264     };
265
266     // Create aliases in the default namespace
267     desc('Create a new version and release.');
268     task('publish', self.prereqs.concat(['version', 'release']
269       .map(prefixNs)));
270
271     desc('Release the existing version.');
272     task('publishExisting', self.prereqs.concat(['release']
273       .map(prefixNs)));
274
275     task('version', ['fetchTags', 'getCurrentBranch', 'pushVersion']
276       .map(prefixNs));
277
278     task('release', ['package', 'publish', 'cleanup']
279       .map(prefixNs));
280
281     // Invoke proactively so there will be a callable 'package' task
282     // which can be used apart from 'publish'
283     jake.Task['publish:definePackage'].invoke();
284   };
285
286 })();
287
288 jake.PublishTask = PublishTask;
289 exports.PublishTask = PublishTask;
290