From 615323318e865f3589ece35848663e96e2232a8a Mon Sep 17 00:00:00 2001 From: AIT LAARAJ Date: Wed, 21 Sep 2016 17:38:18 +0100 Subject: [PATCH 01/13] feat: add gulp tasks for jshint check --- .gitignore | 4 ++ .jshintrc | 66 ++++++++++++++++++++ config.json | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++ gulpfile.js | 37 +++++++++++ package.json | 9 ++- 5 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 .jshintrc create mode 100644 config.json create mode 100644 gulpfile.js diff --git a/.gitignore b/.gitignore index e920c16..f30c43b 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,7 @@ node_modules # Optional REPL history .node_repl_history + +# Generated folders and files +cap +records diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..3730508 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,66 @@ +{ + "predef" : ["gs", "g_form", "g_user"], + "bitwise": true, + "curly": true, + "eqeqeq": true, + "forin": true, + "immed": true, + "latedef": true, + "newcap": true, + "noarg": true, + "noempty": true, + "camelcase" : true, + "nonew": false, + "plusplus": true, + "regexp": false, + "undef": true, + "strict": true, + "trailing": false, + "asi": false, + "boss": false, + "debug": false, + "eqnull": false, + "es3": true, + "esnext": false, + "evil": false, + "expr": false, + "unused": true, + "indent": 2, + "funcscope": false, + "globalstrict": false, + "iterator": false, + "lastsemic": false, + "laxbreak": false, + "laxcomma": false, + "loopfunc": false, + "multistr": false, + "onecase": true, + "proto": false, + "regexdash": false, + "scripturl": false, + "smarttabs": true, + "shadow": false, + "sub": false, + "supernew": false, + "validthis": true, + "browser": true, + "couch": false, + "devel": false, + "dojo": false, + "jquery": false, + "mootools": false, + "node": false, + "nonstandard": false, + "prototypejs": false, + "rhino": false, + "wsh": false, + "nomen": false, + "onevar": true, + "passfail": false, + "white": true, + "maxlen": 80, + "maxparams" : 1, + "maxdepth" : 1, + "maxstatements" : 1, + "maxerr": 100 +} \ No newline at end of file diff --git a/config.json b/config.json new file mode 100644 index 0000000..ec2390f --- /dev/null +++ b/config.json @@ -0,0 +1,172 @@ +{ + "roots": { + "C:/Users/laitlaar/Documents/codesquare/sn-filesync/records": { + "host": "dev11936.service-now.com", + "auth": "YWRtaW46Ymlzc21pbGxhaA==" + } + }, + "search": { + "mine": { + "query": "active=true^sys_updated_by=javascript:gs.getUserName()^ORsys_created_by=javascript:gs.getUserName()^ORDERBYDESCsys_updated_on", + "records_per_search": "10" + }, + "my_app": { + "query": "sys_scope=61bde7134fd122009d184a318110c761", + "records_per_search": "100", + "download": true + }, + "script_includes": { + "table": "sys_script_include", + "query": "sys_scope=61bde7134fd122009d184a318110c761", + "records_per_search": "50", + "download": true + }, + "ui_script": { + "table": "sys_ui_script", + "query": "sys_scope=61bde7134fd122009d184a318110c761", + "records_per_search": "50", + "download": true + }, + "business_rules": { + "table": "sys_script", + "query": "sys_scope=61bde7134fd122009d184a318110c761", + "records_per_search": "50", + "download": true + } + }, + "debug": false, + "folders": { + "business_rules": { + "table": "sys_script", + "key": "name", + "fields": { + "js": "script" + }, + "subDirPattern": "collection/when", + "_custom": true + }, + "client_scripts": { + "table": "sys_script_client", + "key": "name", + "fields": { + "js": "script" + }, + "subDirPattern": "table/type", + "_custom": true + }, + "processors": { + "table": "sys_processor", + "key": "name", + "fields": { + "js": "script" + }, + "_custom": true + }, + "script_actions": { + "table": "sysevent_script_action", + "key": "name", + "fields": { + "js": "script" + }, + "subDirPattern": "event_name", + "_custom": true + }, + "script_includes": { + "table": "sys_script_include", + "key": "name", + "fields": { + "js": "script" + }, + "subDirPattern": "client_", + "_custom": true + }, + "style_sheets": { + "table": "content_css", + "key": "name", + "fields": { + "css": "style" + }, + "_custom": true + }, + "ui_actions": { + "table": "sys_ui_action", + "key": "name", + "fields": { + "js": "script" + }, + "subDirPattern": "table/client_", + "_custom": true + }, + "ui_macros": { + "table": "sys_ui_macro", + "key": "name", + "fields": { + "xhtml": "xml" + }, + "subDirPattern": "category", + "_custom": true + }, + "ui_pages": { + "table": "sys_ui_page", + "key": "name", + "fields": { + "xhtml": "html", + "client.js": "client_script", + "server.js": "processing_script" + }, + "subDirPattern": "category", + "_custom": true + }, + "ui_scripts": { + "table": "sys_ui_script", + "key": "name", + "fields": { + "js": "script" + }, + "_custom": true + }, + "dynamic_content_blocks": { + "table": "content_block_programmatic", + "key": "name", + "fields": { + "xhtml": "programmatic_content" + }, + "subDirPattern": "category", + "_custom": true + }, + "email_templates": { + "table": "sysevent_email_template", + "key": "name", + "fields": { + "html": "message_html" + }, + "subDirPattern": "collection", + "_custom": true + }, + "fix_scripts": { + "table": "sys_script_fix", + "key": "name", + "fields": { + "js": "script" + }, + "_custom": true + }, + "catalog_client_scripts": { + "table": "catalog_script_client", + "key": "name", + "fields": { + "js": "script" + }, + "subDirPattern": "applies_to_/type", + "_custom": true + }, + "sys_web_service": { + "table": "sys_web_service", + "key": "name", + "fields": { + "js": "script" + }, + "_custom": true + } + } +} \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..6e9063e --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,37 @@ +var gulp = require('gulp'), + shell = require('gulp-shell'), + jshint = require('gulp-jshint'), + stylish = require('jshint-stylish'), + runSequence = require('run-sequence'); + +var options = require('minimist')(process.argv.slice(2)); + +gulp.task('default', function() { + //run a sequence of tasks +}); + +gulp.task('jshint-client', function () { + return gulp.src(['./lib/*.js', './cap/ui_scripts/*.js', './src/business_rules/*.js']) + .pipe(jshint()) + .pipe(jshint.reporter('jshint-stylish')); +}); + +gulp.task('jshint-server', function () { + return gulp.src(['./lib/*.js','./cap/script_includes/*.js']) + .pipe(jshint()) + .pipe(jshint.reporter(stylish)); +}); + +gulp.task('jshint', function (callback) { + /** + * This will run in this order: + * jshint-client + * jshint-client and jshint-server in parallel + * jshint-server + * Finally call the callback function + */ + runSequence('jshint-client', + //['jshint-client', 'jshint-server'], + 'jshint-server', + callback); +}) \ No newline at end of file diff --git a/package.json b/package.json index 128355a..ba8ee4a 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,14 @@ "engines": { "node": ">=4.2.6 || >=5.0" }, - "devDependencies": {}, + "devDependencies": { + "gulp": "^3.9.1", + "gulp-jshint": "^2.0.1", + "gulp-shell": "^0.5.2", + "jshint": "^2.9.3", + "jshint-stylish": "^2.2.1", + "run-sequence": "^1.2.2" + }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, From 4dbeb21382ec5e0c4aae8b4c26121e29556fc268 Mon Sep 17 00:00:00 2001 From: AIT LAARAJ Date: Fri, 23 Sep 2016 10:50:02 +0100 Subject: [PATCH 02/13] feat: add jshint task and change some jshint options --- .jshintrc | 16 +++++++--------- gulpfile.js | 4 ++-- package.json | 1 + 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/.jshintrc b/.jshintrc index 3730508..a805ae1 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,17 +1,17 @@ { - "predef" : ["gs", "g_form", "g_user"], + "predef" : ["gs", "g_form", "g_user", "angular"], "bitwise": true, "curly": true, "eqeqeq": true, "forin": true, - "immed": true, - "latedef": true, + "immed": false, + "latedef": false, "newcap": true, "noarg": true, "noempty": true, "camelcase" : true, "nonew": false, - "plusplus": true, + "plusplus": false, "regexp": false, "undef": true, "strict": true, @@ -20,8 +20,6 @@ "boss": false, "debug": false, "eqnull": false, - "es3": true, - "esnext": false, "evil": false, "expr": false, "unused": true, @@ -59,8 +57,8 @@ "passfail": false, "white": true, "maxlen": 80, - "maxparams" : 1, - "maxdepth" : 1, - "maxstatements" : 1, + "maxparams" : 5, + "maxdepth" : 5, + "maxstatements" : false, "maxerr": 100 } \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 6e9063e..5edc761 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -11,13 +11,13 @@ gulp.task('default', function() { }); gulp.task('jshint-client', function () { - return gulp.src(['./lib/*.js', './cap/ui_scripts/*.js', './src/business_rules/*.js']) + return gulp.src(['./lib/*.js', './sncapappsfrancedev/ui_scripts/*.js', './sncapappsfrancedev/business_rules/*.js']) .pipe(jshint()) .pipe(jshint.reporter('jshint-stylish')); }); gulp.task('jshint-server', function () { - return gulp.src(['./lib/*.js','./cap/script_includes/*.js']) + return gulp.src(['./lib/*.js','./sncapappsfrancedev/script_includes/*.js']) .pipe(jshint()) .pipe(jshint.reporter(stylish)); }); diff --git a/package.json b/package.json index ba8ee4a..ba97772 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "gulp": "^3.9.1", "gulp-jshint": "^2.0.1", "gulp-shell": "^0.5.2", + "jscs": "^3.0.7", "jshint": "^2.9.3", "jshint-stylish": "^2.2.1", "run-sequence": "^1.2.2" From 40d58a63f3412e4f9a25f24dddae7c042671923e Mon Sep 17 00:00:00 2001 From: AIT LAARAJ Date: Fri, 23 Sep 2016 10:52:13 +0100 Subject: [PATCH 03/13] feat: installing jscs and using airbnb preset --- .jscsrc | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .jscsrc diff --git a/.jscsrc b/.jscsrc new file mode 100644 index 0000000..58e8c09 --- /dev/null +++ b/.jscsrc @@ -0,0 +1,3 @@ +{ + "preset": "airbnb" +} \ No newline at end of file From 36d00becfd9bf99caea4a30daace53aee642b0fb Mon Sep 17 00:00:00 2001 From: Ait Laaraj Layla Date: Mon, 10 Oct 2016 08:42:47 +0100 Subject: [PATCH 04/13] Update config.json --- config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index ec2390f..5e30a97 100644 --- a/config.json +++ b/config.json @@ -2,7 +2,7 @@ "roots": { "C:/Users/laitlaar/Documents/codesquare/sn-filesync/records": { "host": "dev11936.service-now.com", - "auth": "YWRtaW46Ymlzc21pbGxhaA==" + "auth": "" } }, "search": { @@ -169,4 +169,4 @@ "_custom": true } } -} \ No newline at end of file +} From c447e3a305f15c2064161050c20d0cc9bd6235a2 Mon Sep 17 00:00:00 2001 From: Ait Laaraj Layla Date: Tue, 11 Oct 2016 11:08:13 +0100 Subject: [PATCH 05/13] Update notify.js --- lib/notify.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/notify.js b/lib/notify.js index 5f0cb9d..ffbcce0 100644 --- a/lib/notify.js +++ b/lib/notify.js @@ -27,6 +27,7 @@ function notifyUser() { RECEIVED_FILE_0_BYTES: -20, RECORD_NOT_FOUND: -2.1, NOT_IN_SYNC: -3, + CONFLICTS_DETECTED: -4, COMPLEX_ERROR: -500 }; @@ -95,6 +96,13 @@ function notifyUser() { subtitle: 'Please update your local version first!', message: args.file + ' (' + args.table + ':' + args.field + ')' }; + } else if (code == codes.CONFLICTS_DETECTED) { + notifyArgs = { + type: 'fail', + title: 'Conflicts detected!', + subtitle: 'Please fix conflicts before processing!', + message: args.file + ' (' + args.table + ':' + args.field + ')' + }; } else if (code == codes.RECEIVED_FILE_0_BYTES) { notifyArgs = { type: 'info', From 9dc607eb578bf1b648617be5403d3035308e97f9 Mon Sep 17 00:00:00 2001 From: Ait Laaraj Layla Date: Tue, 11 Oct 2016 11:10:52 +0100 Subject: [PATCH 06/13] Update app.js --- bin/app.js | 315 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 237 insertions(+), 78 deletions(-) diff --git a/bin/app.js b/bin/app.js index 0158e97..30ff7b5 100755 --- a/bin/app.js +++ b/bin/app.js @@ -3,8 +3,6 @@ // --------------------------------------------------- // 3rd party modules -var argv = require('minimist')(process.argv.slice(2)); -//console.dir(argv); var chokidar = require('chokidar'); require('colors'); @@ -15,6 +13,7 @@ var crypto = require('crypto'); var glob = require("glob"); var winston = require('winston'); var moment = require('moment'); +var inquirer = require('inquirer'); // --------------------------------------------------- // custom imports @@ -62,11 +61,60 @@ var filesInQueueToDownload = 0, // a list of FileRecord objects indexed by file path for easy access var fileRecords = {}; -// set to true to exit after a download is complete (avoids watcher starting) +// set to true to exit after a dwd is complete (avoids watcher starting) var endApp = false; // --------------------------------------------------- +var argv = require('minimist')(process.argv.slice(2)); +//console.dir(argv); +// +var jsdiff = require('diff'), + myDiff = new jsdiff.Diff(); + +myDiff.tokenize = function(value) { + return value.split(/(\n|\r\n)/); +}; + +/** + * Diffs two file contents. + * @param {String} file file name where diff results will be output. + * @param {String} local local file content + * @param {String} head serviceNow instance file + * @return {String} The difference between the two file + * elements present only on the instance are surrounded by an (>>>>> *** ==== HEAD) block + * elements present only in the local file are surrounded by an (>>>>> *** ==== Local) block + */ +function diffFiles(file, local, head) { + "use strict"; + var value = '', + isNewLn, + regExp = new RegExp(/^(\n|\r\n|\n\n|\r\n\r\n)$/i), + endSeparator, + startSeparator, + // diffs = jsdiff.diffLines(local, head); + diffs = myDiff.diff(local, head); + + diffs.forEach(function(part){ + endSeparator = regExp.test(part.value.charAt(part.value.length -1)) ? "" : "\n"; + startSeparator = regExp.test(part.value.charAt(0)) ? "" : "\n"; + isNewLn = regExp.test(part.value); + + if (!isNewLn) { + if (part.removed) { + value += "\n>>>>>>>>>>" + startSeparator + part.value + endSeparator + "========== Local"; + } else if (part.added) { + value += "\n>>>>>>>>>>" + startSeparator + part.value + endSeparator + "========== HEAD"; + } else { + value += '\n' + part.value; + } + + } + }); + + return value; +} + // entry point function init() { @@ -474,27 +522,33 @@ function processFoundRecords(searchObj, queryObj, records) { } filePath += fileName; - // ensure we have a valid file name - if (fileSystemSafeName.length === 0) { - totalErrors++; - failedFiles.push(filePath); - continue; - } - - validData = record.recordData.length > 0 || record.recordData.sys_id; - if (validData) { - logit.info('File to create: ' + filePath); + //case it is a pull operation compare local with remote to decide if we wanna overwrite local file + //or push it to the remote + if (argv.pull) { + send(filePath); } else { - logit.info('Found but will ignore due to no content: ' + filePath); - totalErrors++; - failedFiles.push(filePath); - } + // ensure we have a valid file name + if (fileSystemSafeName.length === 0) { + totalErrors++; + failedFiles.push(filePath); + continue; + } - if (queryObj.download) { - // don't save files of 0 bytes as this will confuse everyone + validData = record.recordData.length > 0 || record.recordData.sys_id; if (validData) { - totalFilesToSave++; - saveFoundFile(filePath, record); + logit.info('File to create: ' + filePath); + } else { + logit.info('Found but will ignore due to no content: ' + filePath); + totalErrors++; + failedFiles.push(filePath); + } + + if (queryObj.download) { + // don't save files of 0 bytes as this will confuse everyone + if (validData) { + totalFilesToSave++; + saveFoundFile(filePath, record); + } } } } @@ -1044,14 +1098,16 @@ function push(snc, db, callback) { }); } -function send(file, callback) { - // default callback - callback = callback || function (complete) { - if (!complete) { - logit.error(('Could not send file: ' + file).red); - } - }; + + +/** + * Check if there are conflicts between local and remote script. + * @param {String} file local file + * @param {Function} callback + * + */ +function checkConflicts(file, callback) { readFile(file, function (data) { var map = fileRecords[file].getSyncMap(), @@ -1068,57 +1124,161 @@ function send(file, callback) { // payload for a record update (many fields and values can be set) db.payload[db.field] = data; + var options = { + "db": db, + "snc": snc, + "map": map, + "callback": callback + }, + choices, + subs = ['>>>>', '==== HEAD', '==== Local']; // only allow an update if the instance is still in sync with the local env. instanceInSync(snc, db, map, file, data, function (err, obj) { if (!obj.inSync) { - notifyUser(msgCodes.NOT_IN_SYNC, { + notifyUser(msgCodes.CONFLICTS_DETECTED, { table: map.table, file: map.keyValue, field: map.field, open: fileRecords[file].getRecordUrl() }); - logit.warn('Instance record is not in sync with local env ("%s").', map.keyValue); - callback(false); - return; + + if (new RegExp(subs.join("|")).test(data)) { + logit.error('could not process this action!'.red); + logit.info('Please make sure all conflicts in ("%s") are resolved!.'.red, map.keyValue); + callback(false); + return; + } + + if (argv.push) { + choices = [ + 'overwrite file in ServiceNow', + 'resolve conflicts', + 'abort this action' + ]; + } else if (argv.pull) { + choices = [ + 'overwrite local file', + 'resolve conflicts', + 'abort this action' + ]; + } + + inquireUserInput(options, file, choices, obj); } if (obj.noPushNeeded) { - logit.info('Local has no changes or remote in sync; no need for push/send.'); + logit.info('Local has no changes or remote in sync; no need for push/pull.'); callback(true); return; } + }); + }); +} +/** + * Display a log of diffs in the console terminal. + * @param {String} diffs Diffs to show in the console + */ +function displayPatch (diffs) { + var logs = ''; + + diffs = diffs.split(/(\n|\r\n)/); + + for (var i = 0; i < diffs.length - 1; i++) { + if (diffs[i].charAt(0) === "-") { + logs += diffs[i].red; + } else if (diffs[i].charAt(0) === "+") { + logs += diffs[i].green; + } else { + logs += diffs[i]; + } + } + logit.info(logs); +} - logit.info('Updating instance version ("%s").', map.keyValue); - push(snc, db, function (complete) { - if (complete) { - // update hash for collision detection - fileRecords[file].saveHash(data, function (saved) { - if (saved) { - notifyUser(msgCodes.UPLOAD_COMPLETE, { - file: map.keyValue, - open: fileRecords[file].getRecordUrl() - }); - logit.info('Updated instance version: %s.%s : query: %s', db.table, db.field, db.query); - logit.debug('Updated instance version:', db); - - } else { - notifyUser(msgCodes.COMPLEX_ERROR); - } - callback(saved); - }); - } else { - notifyUser(msgCodes.UPLOAD_ERROR, { - file: map.keyValue, - open: fileRecords[file].getRecordUrl() - }); - callback(complete); - } - - }); +/** + * Inquire user response whether he want to overwrite or resolve conflicts + * @param {object} options An object containing usefull parameters used by the function + * @param {String} file Local file + * @param {Array} choices a list of choices to prompt to the user + * @param {Object} obj An object presenting the remote script + * + */ +function inquireUserInput (options, file, choices, obj) { + var map = options.map, + db = options.db, + snc = options.snc, + data = options.db.payload[db.field], + callback = options.callback, + diffPatch = jsdiff.createPatch(file, data, obj.records[0][map.field]), + conflictsValue = diffFiles(file, data, obj.records[0][map.field]); + + inquirer + .prompt([ + { + type: 'list', + message: 'Conflict on file: '+ file, + name: 'conflict', + choices: choices + }]) + .then(function (answers) { + if (answers['conflict'] === 'resolve conflicts') { + logit.warn('Please resole conflicts in ("%s") before pushing changes.', map.keyValue); + fs.writeFile(file, conflictsValue, "UTF-8"); + displayPatch(diffPatch); + callback(false); + return; + } else if (answers['conflict'] === 'overwrite file in ServiceNow') { + logit.info('Updating instance version ("%s").', map.keyValue); + push(snc, db, function (complete) { + if (complete) { + // update hash for collision detection + fileRecords[file].saveHash(data, function (saved) { + if (saved) { + notifyUser(msgCodes.UPLOAD_COMPLETE, { + file: map.keyValue, + open: fileRecords[file].getRecordUrl() + }); + logit.info('Updated instance version: %s.%s : query: %s', db.table, db.field, db.query); + logit.debug('Updated instance version:', db); + logit.info('Action done successfully'); + return; + } else { + notifyUser(msgCodes.COMPLEX_ERROR); + } + callback(saved); + }); + } else { + notifyUser(msgCodes.UPLOAD_ERROR, { + file: map.keyValue, + open: fileRecords[file].getRecordUrl() + }); + callback(complete); + } + }); + } else if (answers['conflict'] === 'overwrite local file') { + fs.writeFile(file, obj.records[0][map.field]); + logit.info('Local file has overwritten successfully.'); + return; + }else { + logit.info('Action aborted.'); + return; + } + }); - }); +} + +function send(file, callback) { + + // default callback + callback = callback || function (complete) { + if (!complete) { + logit.error(('Could not send file: ' + file).red); + } + }; + + checkConflicts(file, callback); } function addFile(file, callback) { @@ -1207,17 +1367,6 @@ function trackFile(file) { */ function instanceInSync(snc, db, map, file, newData, callback) { - // first lets really check if we have a change - var previousLocalVersionHash = fileRecords[file].getLocalHash(); - var newDataHash = makeHash(newData); - if (previousLocalVersionHash == newDataHash) { - callback(false, { - inSync: true, - noPushNeeded: true - }); - return; // no changes - } - logit.info('Comparing remote version with previous local version...'); snc.table(db.table).getRecords(db, function (err, obj) { @@ -1234,14 +1383,19 @@ function instanceInSync(snc, db, map, file, newData, callback) { logit.debug('Received:'.green, db); var remoteVersion = obj.records[0][db.field], - remoteHash = makeHash(remoteVersion); + remoteHash = makeHash(remoteVersion), + previousLocalVersionHash = fileRecords[file].getLocalHash(), + newDataHash = makeHash(newData); // CASE 1. Records local and remote are the same if (newDataHash == remoteHash) { // handle the scenario where the remote version was changed to match the local version. // when this happens update the local hash as there would be no collision here (and nothing to push!) - obj.inSync = true; - obj.noPushNeeded = true; + callback(false, { + inSync: true, + noPushNeeded: true + }); + return; // no changes // update local hash. fileRecords[file].saveHash(newData, function (saved) { if (!saved) { @@ -1250,11 +1404,16 @@ function instanceInSync(snc, db, map, file, newData, callback) { }); // CASE 2. the last local downloaded version matches the server version (stanard collision test scenario) - } else if (remoteHash == previousLocalVersionHash) { + // and no changes have been made on the local file + } else if (remoteHash == previousLocalVersionHash && newDataHash === remoteHash) { obj.inSync = true; + //CASE 3, the remote version and the local version not in sync + } else if ( newDataHash !== remoteHash) { + // case no local change but server changes + // case local changes but server remains intact + // case both local and server change + callback(err, obj); } - // CASE 3, the remote version changed since we last downloaded it = not in sync - callback(err, obj); }); } From 88c3598917d2aa9d22baff260de1869d3a2eb696 Mon Sep 17 00:00:00 2001 From: ait laaraj layla Date: Tue, 11 Oct 2016 22:39:49 +0100 Subject: [PATCH 07/13] feat: handle conflicts when detected in a file --- bin/app.js | 1 - gulpfile.js | 4 ++-- lib/notify.js | 2 +- package.json | 2 ++ 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/bin/app.js b/bin/app.js index 30ff7b5..23e927d 100755 --- a/bin/app.js +++ b/bin/app.js @@ -92,7 +92,6 @@ function diffFiles(file, local, head) { regExp = new RegExp(/^(\n|\r\n|\n\n|\r\n\r\n)$/i), endSeparator, startSeparator, - // diffs = jsdiff.diffLines(local, head); diffs = myDiff.diff(local, head); diffs.forEach(function(part){ diff --git a/gulpfile.js b/gulpfile.js index 5edc761..ed3becf 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -11,13 +11,13 @@ gulp.task('default', function() { }); gulp.task('jshint-client', function () { - return gulp.src(['./lib/*.js', './sncapappsfrancedev/ui_scripts/*.js', './sncapappsfrancedev/business_rules/*.js']) + return gulp.src(['./lib/*.js', './records/ui_scripts/*.js', './records/business_rules/*.js']) .pipe(jshint()) .pipe(jshint.reporter('jshint-stylish')); }); gulp.task('jshint-server', function () { - return gulp.src(['./lib/*.js','./sncapappsfrancedev/script_includes/*.js']) + return gulp.src(['./lib/*.js','./records/script_includes/*.js']) .pipe(jshint()) .pipe(jshint.reporter(stylish)); }); diff --git a/lib/notify.js b/lib/notify.js index ffbcce0..d027262 100644 --- a/lib/notify.js +++ b/lib/notify.js @@ -99,7 +99,7 @@ function notifyUser() { } else if (code == codes.CONFLICTS_DETECTED) { notifyArgs = { type: 'fail', - title: 'Conflicts detected!', + title: 'Conflicts in file!', subtitle: 'Please fix conflicts before processing!', message: args.file + ' (' + args.table + ':' + args.field + ')' }; diff --git a/package.json b/package.json index ba97772..63d5451 100644 --- a/package.json +++ b/package.json @@ -23,9 +23,11 @@ "node": ">=4.2.6 || >=5.0" }, "devDependencies": { + "diff": "^3.0.1", "gulp": "^3.9.1", "gulp-jshint": "^2.0.1", "gulp-shell": "^0.5.2", + "inquirer": "^1.2.2", "jscs": "^3.0.7", "jshint": "^2.9.3", "jshint-stylish": "^2.2.1", From 1b554f8e71078ada395d85a41e2272e59690b50e Mon Sep 17 00:00:00 2001 From: Ait Laaraj Layla Date: Tue, 11 Oct 2016 22:44:37 +0100 Subject: [PATCH 08/13] Delete config.json --- config.json | 172 ---------------------------------------------------- 1 file changed, 172 deletions(-) delete mode 100644 config.json diff --git a/config.json b/config.json deleted file mode 100644 index 5e30a97..0000000 --- a/config.json +++ /dev/null @@ -1,172 +0,0 @@ -{ - "roots": { - "C:/Users/laitlaar/Documents/codesquare/sn-filesync/records": { - "host": "dev11936.service-now.com", - "auth": "" - } - }, - "search": { - "mine": { - "query": "active=true^sys_updated_by=javascript:gs.getUserName()^ORsys_created_by=javascript:gs.getUserName()^ORDERBYDESCsys_updated_on", - "records_per_search": "10" - }, - "my_app": { - "query": "sys_scope=61bde7134fd122009d184a318110c761", - "records_per_search": "100", - "download": true - }, - "script_includes": { - "table": "sys_script_include", - "query": "sys_scope=61bde7134fd122009d184a318110c761", - "records_per_search": "50", - "download": true - }, - "ui_script": { - "table": "sys_ui_script", - "query": "sys_scope=61bde7134fd122009d184a318110c761", - "records_per_search": "50", - "download": true - }, - "business_rules": { - "table": "sys_script", - "query": "sys_scope=61bde7134fd122009d184a318110c761", - "records_per_search": "50", - "download": true - } - }, - "debug": false, - "folders": { - "business_rules": { - "table": "sys_script", - "key": "name", - "fields": { - "js": "script" - }, - "subDirPattern": "collection/when", - "_custom": true - }, - "client_scripts": { - "table": "sys_script_client", - "key": "name", - "fields": { - "js": "script" - }, - "subDirPattern": "table/type", - "_custom": true - }, - "processors": { - "table": "sys_processor", - "key": "name", - "fields": { - "js": "script" - }, - "_custom": true - }, - "script_actions": { - "table": "sysevent_script_action", - "key": "name", - "fields": { - "js": "script" - }, - "subDirPattern": "event_name", - "_custom": true - }, - "script_includes": { - "table": "sys_script_include", - "key": "name", - "fields": { - "js": "script" - }, - "subDirPattern": "client_", - "_custom": true - }, - "style_sheets": { - "table": "content_css", - "key": "name", - "fields": { - "css": "style" - }, - "_custom": true - }, - "ui_actions": { - "table": "sys_ui_action", - "key": "name", - "fields": { - "js": "script" - }, - "subDirPattern": "table/client_", - "_custom": true - }, - "ui_macros": { - "table": "sys_ui_macro", - "key": "name", - "fields": { - "xhtml": "xml" - }, - "subDirPattern": "category", - "_custom": true - }, - "ui_pages": { - "table": "sys_ui_page", - "key": "name", - "fields": { - "xhtml": "html", - "client.js": "client_script", - "server.js": "processing_script" - }, - "subDirPattern": "category", - "_custom": true - }, - "ui_scripts": { - "table": "sys_ui_script", - "key": "name", - "fields": { - "js": "script" - }, - "_custom": true - }, - "dynamic_content_blocks": { - "table": "content_block_programmatic", - "key": "name", - "fields": { - "xhtml": "programmatic_content" - }, - "subDirPattern": "category", - "_custom": true - }, - "email_templates": { - "table": "sysevent_email_template", - "key": "name", - "fields": { - "html": "message_html" - }, - "subDirPattern": "collection", - "_custom": true - }, - "fix_scripts": { - "table": "sys_script_fix", - "key": "name", - "fields": { - "js": "script" - }, - "_custom": true - }, - "catalog_client_scripts": { - "table": "catalog_script_client", - "key": "name", - "fields": { - "js": "script" - }, - "subDirPattern": "applies_to_/type", - "_custom": true - }, - "sys_web_service": { - "table": "sys_web_service", - "key": "name", - "fields": { - "js": "script" - }, - "_custom": true - } - } -} From 42a2186cb4de9d1ee3fe90a9b4b7af8eea1d0739 Mon Sep 17 00:00:00 2001 From: Ait Laaraj Layla Date: Tue, 11 Oct 2016 22:48:18 +0100 Subject: [PATCH 09/13] Delete gulpfile.js --- gulpfile.js | 37 ------------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 gulpfile.js diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index ed3becf..0000000 --- a/gulpfile.js +++ /dev/null @@ -1,37 +0,0 @@ -var gulp = require('gulp'), - shell = require('gulp-shell'), - jshint = require('gulp-jshint'), - stylish = require('jshint-stylish'), - runSequence = require('run-sequence'); - -var options = require('minimist')(process.argv.slice(2)); - -gulp.task('default', function() { - //run a sequence of tasks -}); - -gulp.task('jshint-client', function () { - return gulp.src(['./lib/*.js', './records/ui_scripts/*.js', './records/business_rules/*.js']) - .pipe(jshint()) - .pipe(jshint.reporter('jshint-stylish')); -}); - -gulp.task('jshint-server', function () { - return gulp.src(['./lib/*.js','./records/script_includes/*.js']) - .pipe(jshint()) - .pipe(jshint.reporter(stylish)); -}); - -gulp.task('jshint', function (callback) { - /** - * This will run in this order: - * jshint-client - * jshint-client and jshint-server in parallel - * jshint-server - * Finally call the callback function - */ - runSequence('jshint-client', - //['jshint-client', 'jshint-server'], - 'jshint-server', - callback); -}) \ No newline at end of file From 7d3b97dc84e2a59ae5c51fc2942d76001b7dcc0e Mon Sep 17 00:00:00 2001 From: Ait Laaraj Layla Date: Tue, 11 Oct 2016 22:49:23 +0100 Subject: [PATCH 10/13] Update package.json --- package.json | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/package.json b/package.json index 63d5451..8c600d6 100644 --- a/package.json +++ b/package.json @@ -24,14 +24,7 @@ }, "devDependencies": { "diff": "^3.0.1", - "gulp": "^3.9.1", - "gulp-jshint": "^2.0.1", - "gulp-shell": "^0.5.2", - "inquirer": "^1.2.2", - "jscs": "^3.0.7", - "jshint": "^2.9.3", - "jshint-stylish": "^2.2.1", - "run-sequence": "^1.2.2" + "inquirer": "^1.2.2" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" From 000e60d31f6e92b1ddedb46d4f7af8ac073be942 Mon Sep 17 00:00:00 2001 From: Ait Laaraj Layla Date: Tue, 11 Oct 2016 22:49:53 +0100 Subject: [PATCH 11/13] Delete .jshintrc --- .jshintrc | 64 ------------------------------------------------------- 1 file changed, 64 deletions(-) delete mode 100644 .jshintrc diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index a805ae1..0000000 --- a/.jshintrc +++ /dev/null @@ -1,64 +0,0 @@ -{ - "predef" : ["gs", "g_form", "g_user", "angular"], - "bitwise": true, - "curly": true, - "eqeqeq": true, - "forin": true, - "immed": false, - "latedef": false, - "newcap": true, - "noarg": true, - "noempty": true, - "camelcase" : true, - "nonew": false, - "plusplus": false, - "regexp": false, - "undef": true, - "strict": true, - "trailing": false, - "asi": false, - "boss": false, - "debug": false, - "eqnull": false, - "evil": false, - "expr": false, - "unused": true, - "indent": 2, - "funcscope": false, - "globalstrict": false, - "iterator": false, - "lastsemic": false, - "laxbreak": false, - "laxcomma": false, - "loopfunc": false, - "multistr": false, - "onecase": true, - "proto": false, - "regexdash": false, - "scripturl": false, - "smarttabs": true, - "shadow": false, - "sub": false, - "supernew": false, - "validthis": true, - "browser": true, - "couch": false, - "devel": false, - "dojo": false, - "jquery": false, - "mootools": false, - "node": false, - "nonstandard": false, - "prototypejs": false, - "rhino": false, - "wsh": false, - "nomen": false, - "onevar": true, - "passfail": false, - "white": true, - "maxlen": 80, - "maxparams" : 5, - "maxdepth" : 5, - "maxstatements" : false, - "maxerr": 100 -} \ No newline at end of file From b17cadc25791a003e2c464626e3759ff763d763e Mon Sep 17 00:00:00 2001 From: Ait Laaraj Layla Date: Tue, 11 Oct 2016 22:50:17 +0100 Subject: [PATCH 12/13] Delete .jscsrc --- .jscsrc | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .jscsrc diff --git a/.jscsrc b/.jscsrc deleted file mode 100644 index 58e8c09..0000000 --- a/.jscsrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "preset": "airbnb" -} \ No newline at end of file From 35af86be34ef2be2ecd4d1e21e987899cfc2190b Mon Sep 17 00:00:00 2001 From: Ait Laaraj Layla Date: Tue, 11 Oct 2016 22:50:56 +0100 Subject: [PATCH 13/13] Update .gitignore --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index f30c43b..a2d10c1 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,3 @@ node_modules # Optional REPL history .node_repl_history -# Generated folders and files -cap -records