diff --git a/lib/index.js b/lib/index.js index aa760fd..567667a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,7 +1,7 @@ /** * Constants */ -const COMMAND = 'crontab'; +var COMMAND = 'crontab'; /** * @ignore @@ -14,41 +14,42 @@ var CronJob = require('./CronJob'); * @class CronTab * A JavaScript representation of a user crontab. Each tab has zero or more cron jobs corresponding * to the individual lines in the cron syntax. - * + * * Examples: * new CronTab('bob', function(err, tab) { * if (err) { console.log(err); process.exit(1); } - * + * * console.log("bob's tab: " + tab.render()); * }); - * + * * new CronTab(function(err, tab) { * if (err) { console.log(err); process.exit(1); } - * + * * console.log("current user's tab: " + tab.render()); * }); - * + * * @param {String} __username__ * @param {Function} __callback__ */ function CronTab(u, cb) { - var self = this; - var user = u || ''; - var root = (process.getuid() == 0); - var backup = {lines:[], jobs:[]}; - var lines = []; - var jobs = []; - + var self = this; + var user = u || ''; + var root = (process.getuid() == 0); + var backup = {lines:[], jobs:[]}; + var lines = []; + var jobs = []; + var pausedFlag = '#paused' + load(cb); - - + + /** * Provides access to the jobs collection. - * + * * Examples: * new CronTab(function(err, tab) { * if (err) { console.log(err); process.exit(1); } - * + * * var jobs = tab.jobs((command:'ls -l /', comment:'this should run every night')); * for (var i = 0; i < jobs.length; i++) { * console.log(jobs[i].render()); @@ -89,20 +90,20 @@ function CronTab(u, cb) { results.push(job); } } - + return results; } this.find = this.jobs; /** * Writes the crontab to the system. Saves all information. - * + * * Examples: * new CronTab(function(err, tab) { * if (err) { console.log(err); process.exit(1); } - * + * * var jobs = tab.jobs({command:'ls -l /'}); * tab.remove(jobs); - * + * * tab.save(function(err, tab) { * if (err) { console.log(err); process.exit(1); } * @@ -121,7 +122,7 @@ function CronTab(u, cb) { child.stdout.setEncoding('utf8'); child.stderr.setEncoding('utf8'); - + child.stdout.on('data', function(chunk) { stdout += chunk; }); @@ -138,17 +139,17 @@ function CronTab(u, cb) { cb && cb({message:stderr}, self); } }); - + child.stdin.write(this.render()); child.stdin.end(); } /** * Renders the object to a string as it would be written to the system. - * + * * Examples: * new CronTab(function(err, tab) { * if (err) { console.log(err); process.exit(1); } - * + * * console.log(tab.render()); * }); * @@ -156,29 +157,29 @@ function CronTab(u, cb) { */ this.render = function() { var tokens = []; - + for (var i = 0; i < lines.length; i++) { var job = lines[i]; - + if (job.isValid && !job.isValid()) { tokens.push('# ' + job.toString()); continue; } - + tokens.push(job.toString()); } - + return tokens.join('\n').trim() + '\n'; } /** * Creates a new job with the specified command, comment and date. - * + * * Examples: * new CronTab(function(err, tab) { * if (err) { console.log(err); process.exit(1); } - * + * * var future = Date.parse('2010/7/11'); - * + * * tab.create('ls -l /'); * tab.create('ls -l /', 'just a silly example'); * tab.create('ls -l /', 'just a silly example', future); @@ -230,11 +231,11 @@ function CronTab(u, cb) { } /** * Removes the specified jobs from the crontab. - * + * * Examples: * new CronTab(function(err, tab) { * if (err) { console.log(err); process.exit(1); } - * + * * var jobs = tab.jobs({command:'ls -l /'}); * tab.remove(jobs); * }); @@ -242,6 +243,8 @@ function CronTab(u, cb) { * @param {String} __Array[CronJob]__ */ this.remove = function(jobs) { + var didRemove = false; + if (jobs instanceof CronJob) { jobs = [jobs]; } @@ -255,20 +258,22 @@ function CronTab(u, cb) { else { jobs = []; } - + for (var i = 0; i < jobs.length; i++) { - remove(jobs[i]); + didRemove = remove(jobs[i]); } - + truncateLines(); + + return didRemove; } /** * Restores this crontab to its original state. - * + * * Examples: * new CronTab(function(err, tab) { * if (err) { console.log(err); process.exit(1); } - * + * * var jobs = tab.jobs({command:'ls -l /'}); * tab.remove(jobs); * tab.reset(); @@ -278,13 +283,108 @@ function CronTab(u, cb) { lines = backup.lines.slice(); jobs = backup.jobs.slice(); } - - + + /** + * Returns all paused jobs + * This uses the `#paused` flag to determine which comemnts are paused jobs + * + * Examples: + * new CronTab(function(err, tab) { + * if (err) { console.log(err); process.exit(1); } + * + * var jobs = tab.pausedJobsjobs(; + * }); + * + * @param {Object} __[options]__ + * @return {Array[CronJob]} + */ + this.pausedJobs = function() { + // This flag identifies 'paused' jobs in the crontab + var pausedTokens = []; + var pausedJobs = []; + + lines.forEach(function(line) { + if (typeof line === 'string') { + var trimmed = line.substring(0, pausedFlag.length); + if (trimmed === pausedFlag) { + pausedTokens.push( + line.slice(pausedFlag.length) + ); + } + } + }); + + if (pausedTokens.length === 0) { + return []; + } + + pausedTokens.forEach(function(token) { + var job = makeJob(token); + if (job !== null && job.isValid()) { + pausedJobs.push(job); + } + }); + + return pausedJobs; + } + /** + * Pause a job + * + * @param {CronJob} + * @return {Boolean} + */ + this.pauseJob = function(job) { + if (!job.isValid()) { + return false; + } + + var command = job.command(); + var removeTask = remove(job); + + if (removeTask) { + var pausedEntry = pausedFlag + job.toString(); + lines.push(pausedEntry); + return true; + } + + return false; + } + /** + * Activate a job + * + * @param {CronJob} + * @return {Boolean} + */ + this.activateJob = function(job) { + var targetIndex; + lines.forEach(function(line, index) { + if (typeof line === 'string') { + var trimmed = line.substring(0, pausedFlag.length); + var command = line.slice(pausedFlag.length); + // Is this a paused job and does it match + if (trimmed === pausedFlag && command === job.toString()) { + targetIndex = index; + } + } + }); + + // Remove the paused job by index + lines.splice(targetIndex, 1); + var activeJob = makeJob(job.toString()); + if (activeJob && activeJob.isValid()) { + // Re-add active, valid job into lines array + lines.push(activeJob); + return true; + } + + return false; + } + /** * Loads the system crontab into this object. * * @param {function} __callback__ - * + * * @api private */ function load(cb) { @@ -293,10 +393,10 @@ function CronTab(u, cb) { var args = makeChildArgs('load'); var command = makeChildCommand(); var child = Spawn(command, args); - + jobs = []; lines = []; - + child.stdout.setEncoding('utf8'); child.stderr.setEncoding('utf8'); @@ -313,12 +413,12 @@ function CronTab(u, cb) { cb && cb({message:stderr}, null); return; } - + var tokens = stdout.split('\n'); for (var i = 0; i < tokens.length; i++) { var token = tokens[i]; var job = makeJob(token); - + if (job != null && job.isValid()) { jobs.push(job); lines.push(job); @@ -327,50 +427,52 @@ function CronTab(u, cb) { lines.push(token); } } - + truncateLines(); - + backup.lines = lines.slice(); backup.jobs = jobs.slice(); - - cb && cb(null, self); + + cb && cb(null, self); }); } /** * Removes the specified job from the crontab. * * @param {CronJob} __job__ - * + * * @api private */ function remove(job) { var oldJobs = jobs; var oldLines = lines; - + jobs = []; lines = []; - + for (var i = 0; i < oldJobs.length; i++) { var oldJob = oldJobs[i]; - + if (oldJob != job) { jobs.push(oldJob); } } for (var i = 0; i < oldLines.length; i++) { var oldLine = oldLines[i]; - + if (oldLine != job) { lines.push(oldLine); } } + + return (oldJobs.length !== jobs.length); } /** * Creates an array of CL arguments for the system "crontab" command. Intended to be passed to * child_process.spawn. * * @param {String} __action__ 'load' | 'save' - * + * * @api private */ function makeChildArgs(action) { @@ -378,21 +480,21 @@ function CronTab(u, cb) { if (user) { args = args.concat('-u', user); } - + if (action == 'load') { args.push('-l'); } if (action == 'save' && process.platform !== 'sunos') { args.push('-'); } - + return args; } /** * Creates a system command string to run crontab. Intended to be passed to * child_process.spawn. If this is going to run for another user and the * current user is not root, we prefix the command with sudo. - * + * * @api private */ function makeChildCommand() { @@ -400,7 +502,7 @@ function CronTab(u, cb) { if (user.length > 0 && root == false) { command = 'sudo ' + command; } - + return command; } /** @@ -410,7 +512,7 @@ function CronTab(u, cb) { * @param {String|null} __line__ * @param {String} __[command]__ * @param {String} __[comment]__ - * + * * @api private */ function makeJob(line, command, comment) { @@ -419,7 +521,6 @@ function CronTab(u, cb) { if (!job || !job.isValid()) { throw 'invalid job'; } - return job; } catch(e) {} @@ -427,17 +528,17 @@ function CronTab(u, cb) { } /** * Compacts the line collection by removes empty lines from the end. - * + * * @api private */ function truncateLines() { var undefined; var line = lines.pop(); - + while (line != undefined && line.toString().trim() == '') { line = lines.pop(); } - + if (line != undefined) { lines.push(line); } @@ -456,5 +557,3 @@ module.exports = { } } }; - -