How to use copyFolder method in ts-auto-mock

Best JavaScript code snippet using ts-auto-mock

copyfolder.js

Source:copyfolder.js Github

copy

Full Screen

1/**2 * Copy Folder Thunderbird Plugin3 *4 * @version copyfolder.js v2.15 * @copyright Copyright(c) 2014 Jonathan Wolinsky6 * @author Jonathan Wolinsky <jwolinsky@gmail.com>7 * @author Steven Hartland <steven.hartland@multiplay.co.uk>8 * @author Yuji Shingai <yshingai@gmail.com>9 */1011if(!com) var com = {};12if(!com.crunchmod) com.crunchmod = {};13if(!com.crunchmod.copyfolder) com.crunchmod.copyfolder = {};1415com.crunchmod.copyfolder.__defineGetter__("FolderLookupService", function() {16 delete com.crunchmod.copyfolder.FolderLookupService;17 return com.crunchmod.copyfolder.FolderLookupService =18 Components.classes['@mozilla.org/mail/folder-lookup;1']19 .getService(Components.interfaces.nsIFolderLookupService);20 });212223ChromeUtils.import('resource:///modules/MailServices.jsm');24ChromeUtils.import('resource:///modules/iteratorUtils.jsm');25ChromeUtils.import("resource:///modules/folderUtils.jsm");2627const Cc = Components.classes;28const Ci = Components.interfaces;2930if ("undefined" == typeof(messenger)) {31 var messenger = Cc["@mozilla.org/messenger;1"].createInstance(Ci.nsIMessenger);32}3334var CopyFolder = {};3536// Preferences37// -----------3839CopyFolder.Prefs = {4041 // const42 preferencePrefix : "extensions.copyfolder.",4344 _prefService: null,4546 get prefService()47 {48 if (!this._prefService)49 this._prefService =50 Components.classes["@mozilla.org/preferences-service;1"]51 .getService(Components.interfaces.nsIPrefBranch);52 return this._prefService;53 },5455 getBoolPref: function(prefName, defaultValue) {56 try {57 return this.prefService.getBoolPref(58 CopyFolder.Prefs.preferencePrefix + prefName);59 } catch(ex) {60 if (defaultValue != undefined)61 return defaultValue;6263 throw(ex);64 }65 },6667 getCharPref: function(prefName, defaultValue) {68 try {69 return this.prefService.getCharPref(70 CopyFolder.Prefs.preferencePrefix + prefName);71 } catch(ex) {72 if (defaultValue) {73 return defaultValue;74 }75 throw(ex);76 }77 },7879 getIntPref: function(prefName, defaultValue) {80 try {81 return this.prefService.getIntPref(82 CopyFolder.Prefs.preferencePrefix + prefName);83 } catch(ex) {84 if (defaultValue)85 return defaultValue;8687 throw(ex);88 }89 },9091 getLocalizedStringPref: function(prefName, defaultValue) {92 try {93 return this.prefService94 .getComplexValue(95 CopyFolder.Prefs.preferencePrefix +96 prefName,Components.interfaces.nsIPrefLocalizedString).data;97 } catch(ex) {98 if (defaultValue) {99 return defaultValue;100 }101 throw(ex);102 }103 },104105 setBoolPref: function(prefName, val) {106 this.prefService.setBoolPref(107 CopyFolder.Prefs.preferencePrefix + prefName, val);108 },109110 setCharPref: function(prefName, val) {111 this.prefService.setCharPref(112 CopyFolder.Prefs.preferencePrefix + prefName, val);113 },114115 setIntPref: function(prefName, val) {116 this.prefService.setIntPref(117 CopyFolder.Prefs.preferencePrefix + prefName, val);118 },119120 setAppStringPref: function(appPrefName, str) {121 if (BiDiMailUI.App.versionIsAtLeast("58.0b1")) {122 BiDiMailUI.Prefs.prefService.setStringPref(appPrefName, str);123 }124 else125 {126 BiDiMailUI.Prefs.prefService.setComplexValue(127 appPrefName, Components.interfaces.nsISupportsString, str);128 }129 },130131 setLocalizedStringPref: function (prefName, val) {132 var pls =133 Components.classes["@mozilla.org/pref-localizedstring;1"]134 .createInstance(Components.interfaces.nsIPrefLocalizedString);135 pls.data = val;136 setAppStringPref(CopyFolder.Prefs.preferencePrefix +137 prefName, pls);138 }139}140141142com.crunchmod.copyfolder = {143 logLevel: 4, // 1: Error, 2: Warn, 3: Info, 4+: Debug144 bRunning: {}, // oncommand関数がメニューの深さ回呼ばれるので回避用 == "preclude simultaneous copies to the destination folder"145146 /**147 * Initiates plugin148 *149 * @return void150 */151 init: function() {152 // remove onLoad listener and set attributes153 window.removeEventListener('load', com.crunchmod.copyfolder.init, false);154 com.crunchmod.copyfolder.statusBar = document.getElementById('statusbar-progresspanel');155 com.crunchmod.copyfolder.progressMeter = document.getElementById('statusbar-icon');156 com.crunchmod.copyfolder.copyfolderStatus = document.getElementById('copyfolder-status');157158159 // create datasources for "Copy To" menuitem160// ver 60 以降使えなくなった == "can no longer be used"161/* let menu = document.getElementById('folderPaneContext-copyfolder');162 if (menu) {163 let prefix = "@mozilla.org/rdf/datasource;1?name=";164 let nsIRDFDataSource = Components.interfaces.nsIRDFDataSource;165 //let accountManagerDataSource = Components.classes[prefix + "msgaccountmanager"].getService(nsIRDFDataSource);166 //let folderDataSource = Components.classes[prefix + "mailnewsfolders"].getService(nsIRDFDataSource);167168 //menu.database.AddDataSource(accountManagerDataSource);169 //menu.database.AddDataSource(folderDataSource);170 menu.setAttribute('ref', 'msgaccounts:/');171 } */172 },173174175176 /**177 * Backward compatibility for old getMsgFolderFromUri global function178 *179 * @param uri the URI to convert into a folder180 * @param checkFolderAttributes whether to check that the folder either has181 * a parent or isn't a server182 * @returns the nsIMsgFolder corresponding to this URI, or null if183 * aCheckFolderAttributes is true and the folder doesn't have a184 * parent or is a server185 */186 getMsgFolderFromUri: function(uri, checkFolderAttributes) {187 let msgfolder = null;188 var { MailUtils } = ChromeUtils.import("resource:///modules/MailUtils.jsm");189190 if (typeof MailUtils != 'undefined' && MailUtils.getExistingFolder) {191 msgFolder = MailUtils.getExistingFolder(uri);192 return msgFolder;193 }194195 try {196 let resource = GetResourceFromUri(uri);197 msgfolder = resource.QueryInterface(Components.interfaces.nsIMsgFolder);198 if (checkFolderAttributes) {199 if (!(msgfolder && (msgfolder.parent || msgfolder.isServer))) {200 msgfolder = null;201 }202 }203 } catch (ex) {204 com.crunchmod.copyfolder.logError('Failed to get the folder resource: ' + ex);205 }206207 return msgfolder;208 },209210 /**211 * Log an error with a timestamp212 *213 * @param string msg the message to log214 * @return void215 */216 logError: function(msg) {217 com.crunchmod.copyfolder.logAtLevel(1, msg);218 },219220 /**221 * Log a warning with a timestamp222 *223 * @param string msg the message to log224 * @return void225 */226 logWarn: function(msg) {227 com.crunchmod.copyfolder.logAtLevel(2, msg);228 },229230 /**231 * Log a message with a timestamp232 *233 * @param string msg the message to log234 * @return void235 */236 logInfo: function(msg) {237 com.crunchmod.copyfolder.logAtLevel(3, msg);238 },239240 /**241 * Log a debug message with a timestamp242 *243 * @param int lvl debug level244 * @param string msg the message to log245 * @return void246 */247 logDebug: function(lvl, msg) {248 com.crunchmod.copyfolder.logAtLevel(lvl + 3, msg);249 },250251 /**252 * Log a message at a level with a timestamp253 *254 * @param int lvl debug level255 * @param string msg the message to log256 * @return void257 */258 logAtLevel: function(lvl, msg) {259 if (lvl > com.crunchmod.copyfolder.logLevel) {260 return;261 }262263 let logFunc;264265 switch(lvl) {266 case 1: // Error267 logFunc = Components.utils.reportError;268 break;269 case 2: // Warning270 // TODO(steve): Should be a warning but that doesn't seem possible.271 // FALLTHROUGH272 logFunc = console.warn;273 break;274 case 3: // Info275 // FALLTHROUGH276 default: // Debug277 // TODO(steve): Should be a debug but that doesn't seem possible.278 logFunc = console.log;279 break;280 }281282 logFunc(new Date().toUTCString() + ': ' + msg);283 },284285 /**286 * Shows confirmation dialog for a copy287 *288 * @param nsIMsgFolder Destination folder.289 * @return void290 */291 copyDialog: function(destFolderSelected) {292 // 複数回呼ばれるので回避策 == "workaround because it is called multiple times"293 if (typeof( com.crunchmod.copyfolder.bRunning[destFolderSelected.URI] ) == "undefined" ) {294 com.crunchmod.copyfolder.bRunning[destFolderSelected.URI] = 1;295 com.crunchmod.copyfolder.transferDialog(destFolderSelected, false);296 }297 return false;298 },299300 /**301 * Shows confirmation dialog for a move302 * Note: move is no yet implemented .303 *304 * @param nsIMsgFolder Destination folder.305 * @return void306 */307 moveDialog: function(destFolderSelected) {308 return com.crunchmod.copyfolder.transferDialog(destFolderSelected, true);309 },310311 /**312 * Shows confirmation dialog for a move or copy313 *314 * @param nsIMsgFolder Destination folder.315 * @param boolean is the transfer a move operation.316 * @return void317 */318 transferDialog: function(destFolderSelected, move) {319 let transfer = new com.crunchmod.copyfolder.transfer(320 gFolderTreeView.getSelectedFolders()[0],321 com.crunchmod.copyfolder.getMsgFolderFromUri(destFolderSelected.URI),322 move);323324 transfer.calculateAndConfirm();325 },326327 /**328 * Sets status message329 *330 * @param string Status message text.331 * @return void332 */333 setStatus: function(text) {334 if (text === null) {335 com.crunchmod.copyfolder.copyfolderStatus.setAttribute('collapsed', true);336 return;337 }338 com.crunchmod.copyfolder.copyfolderStatus.setAttribute('collapsed', false);339 com.crunchmod.copyfolder.copyfolderStatus.setAttribute('label', text);340 },341342 /**343 * Creates a transfer344 *345 * @param nsIMsgFolder srcFolder Folder to copy messages from.346 * @param nsIMsgFolder destFolder Folder to copy messages to.347 * @param boolean is the transfer a move operation.348 * @return transfer object349 */350 transfer: function(srcFolder, destParent, move) {351 var oSrcFolder = srcFolder;352 var oDestParent = destParent;353 var bMove = move;354 var bTreeCopy = (CopyFolder.Prefs.getCharPref('recurse_copy',355 'recurse') == 'recurse');356 var iSuccessCount = 0;357 var iFailedCount = 0;358 var iInflightCount = 0;359 var iCopyCount = 0360 var iSrcNewCount = 0;361 var iSrcTotalCount = 0;362 var iDestTotalCount = 0;363 var iRef = 0;364 var iCompareFolderMissing = 0;365 var copyService = null;366 var notifyService = null;367 var pendingFolderCreates = {};368 var createdFolders = {};369 var pendingFolders = [];370 var inflightMsgs = {};371 var failedTransfers = {};372 var srcFolderEnumerator = null;373 var destFolderEnumerator = null;374 var lastSrcFolder = null;375 var iHashSeed = 92562;376 var transferWatchdogInterval = null;377 var dLastTransferCallback = null;378 var dLastTransferCallbackComplete = null;379 var bAborted = false;380 var bRetried = false;381 var batchTimeout = null;382 var folderTotals = {383 copies: 0,384 successes: 0,385 failures: 0,386 retries: 0387 };388389 // TODO(steve): make these settings extension preferences390 var iInflightMin = 5;391 var iInflightMax = 15; // try 15, orig is 10;392 var iTransferWatchdogWarning = 300000; // 5m393 var iTransferWatchdogRetry = 600000; // 10m394 var iTransferWatchdogAbort = 900000; // 15m395 var iCompareBatchMax = 500;396 var iMaxRetries = 5;397 var iBatchGap = 150; // 150ms?398399 /**400 * Returns the passed string with the first letter capitalised.401 *402 * @param string msg403 * @return string404 */405 var capitalize = function(msg) {406 return msg.charAt(0).toUpperCase() + msg.slice(1);407 };408409 /**410 * Returns the action verb optionally capitalised411 *412 * @param bool bCaptialize if true capitalize the413 * @return string414 */415 var actionVerb = function(bCapitalize) {416 let verb = bMove ? 'move' : 'copy';417 if (bCapitalize) {418 return capitalize(verb);419 }420421 return verb;422 };423424 /**425 * Returns the success verb optionally capitalised426 *427 * @param bool bCaptialize if true capitalize the428 * @return string429 */430 var successVerb = function(bCapitalize) {431 let verb = bMove ? 'moved' : 'copied';432 if (bCapitalize) {433 return capitalize(verb);434 }435436 return verb;437 };438439 /**440 * Returns the path of the aFolder441 *442 * @param nsIMsgFolder aFolder Folder to return the path of.443 * @param nsIMsgFolder aSubFolder optional sub folder.444 * @return string445 */446 var folderPath = function(aFolder, aSubFolder) {447 // We should the able to use relativePathName but its always blank.448 let parts = [];449 if (typeof aSubFolder !== 'undefined') {450 parts.unshift(aSubFolder.prettyName);451 }452453 while (aFolder !== null) {454 parts.unshift(aFolder.prettyName);455 aFolder = aFolder.parent;456 }457458 return parts.join('/');459 };460461 /**462 * Returns the count messages in aFolder, optionally including sub folders463 *464 * @param nsIMsgFolder aFolder Folder to return the count of.465 * @param bool bRecurse include sub folder counts.466 * @return int467 */468 var folderMessageCount = function(aFolder, bRecurse) {469 // We need a de-duplicated count not a raw one and also nsIMsgFolder.getTotalMessages doesn't470 // always agree with the number of messages we can enumerate from the folder so we use our471 // uniqueMsgEnumerator instead..472 let cnt = uniqueMsgEnumerator(aFolder).msgTotal();473 if (bRecurse && aFolder.hasSubFolders) {474 for (let subFolder of fixIterator(aFolder.subFolders, Components.interfaces.nsIMsgFolder)) {475 cnt += folderMessageCount(subFolder, bRecurse);476 }477 }478479 return cnt;480 };481482 /**483 * JS Implementation of MurmurHash3 (r136) (as of May 20, 2011)484 *485 * @author Gary Court <gary.court@gmail.com>486 * @see http://github.com/garycourt/murmurhash-js487 * @author Austin Appleby <aappleby@gmail.com>488 * @see http://sites.google.com/site/murmurhash/489 *490 * @param {string} key ASCII only491 * @param {number} seed Positive integer only492 * @return {number} 32-bit positive integer hash493 */494 var murmurhash3 = function (key, seed) {495 let remainder, bytes, h1, h1b, c1, c1b, c2, c2b, k1, i;496497 remainder = key.length & 3; // key.length % 4498 bytes = key.length - remainder;499 h1 = seed;500 c1 = 0xcc9e2d51;501 c2 = 0x1b873593;502 i = 0;503504 while (i < bytes) {505 k1 =506 ((key.charCodeAt(i) & 0xff)) |507 ((key.charCodeAt(++i) & 0xff) << 8) |508 ((key.charCodeAt(++i) & 0xff) << 16) |509 ((key.charCodeAt(++i) & 0xff) << 24);510 ++i;511512 k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;513 k1 = (k1 << 15) | (k1 >>> 17);514 k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;515516 h1 ^= k1;517 h1 = (h1 << 13) | (h1 >>> 19);518 h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;519 h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));520 }521522 k1 = 0;523524 switch (remainder) {525 case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;526 case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;527 case 1: k1 ^= (key.charCodeAt(i) & 0xff);528529 k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;530 k1 = (k1 << 15) | (k1 >>> 17);531 k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;532 h1 ^= k1;533 }534535 h1 ^= key.length;536537 h1 ^= h1 >>> 16;538 h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;539 h1 ^= h1 >>> 13;540 h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;541 h1 ^= h1 >>> 16;542543 return h1 >>> 0;544 };545546 /**547 * Returns an identifier for the message548 *549 * @param nsIMsgDBHdr msgHdr550 * @return string551 */552 var messageHashCode = function(msgHdr, bIncludeDate) {553 // messageSize and lineCount vary on Gmail, they seem to include the headers when it shouldn't so we cant use them.554 // Messages going through different routes could be the same but have different case on the recipients.555 let parts = [556 msgHdr.subject,557 // subject has re: stripped so include that flag too.558 msgHdr.flags & Components.interfaces.nsMsgMessageFlags.HasRe,559 // This can cause multiple copies as messages can exist without a Date header, which when copied get a new date.560 msgHdr.ccList,561 msgHdr.bccList,562 msgHdr.author,563 msgHdr.recipients564 ];565566 if (bIncludeDate) {567 parts.push(msgHdr.dateInSeconds);568 }569570 // At least when copying to Gmail:571 // * subject gets tabs replaced by spaces on copy572 // * ccList, bccList and author sometimes have multi spaces removed.573 // So we perform a cleanup before hashing to prevent issues.574 return murmurhash3(parts.join(':').replace(/\s+/gm, ' '), iHashSeed);575 };576577 /**578 * Returns true if the msgHdr has an md5 based messageId579 *580 * @param nsIMsgDBHdr msgHdr581 * @return bool582 */583 var hasMd5Id = function(msgHdr) {584 return msgHdr.messageId.substring(0, 4) == "md5:";585 };586587 /**588 * Searches for message in folder589 *590 * @param nsIMsgFolder folder591 * @param nsIMsgDBHdr msgHdr592 * @return boolean593 */594 messageExists = function(folder, msgHdr) {595 if (folder === null) {596 return false;597 }598599 if (destFolderEnumerator !== null && destFolderEnumerator.msgTotal() === 0) {600 return false;601 }602603 let bExists = false;604 try {605 let msgDB = folder.msgDatabase;606 if (msgDB === null) {607 return false;608 }609610 if (msgDB.getMsgHdrForMessageID(msgHdr.messageId) != null) {611 bExists = true;612 } else if (hasMd5Id(msgHdr)) {613 // md5 based messageId's aren't maintained across copies so this message could still exist.614 if (destFolderEnumerator === null) {615 destFolderEnumerator = uniqueMsgEnumerator(folder, true);616 }617618 bExists = destFolderEnumerator.msgExists(msgHdr);619 }620 // Close the db according to:621 // http://mdn.beonex.com/en/Extensions/Thunderbird/HowTos/Common_Thunderbird_Use_Cases/Open_Folder.html622 folder.msgDatabase = null;623 } catch (ex) {624 // TODO(steve): deal with better e.g. force an update?625 com.crunchmod.copyfolder.logError("Failed to check if message exists: ex: " + ex);626 }627628 if (!bExists) {629 com.crunchmod.copyfolder.logDebug(5, "messageExists: folder: " + folder.prettyName + ", messageId: " + msgHdr.messageId + ", subject: " + msgHdr.subject + ", dateInSeconds: " + msgHdr.dateInSeconds + ", date: " + msgHdr.date + " => " + bExists);630 }631632 return bExists;633 };634635 /**636 * Schedule a batch after the batch gap.637 *638 * @param function processFunc see processBatch639 * @param function completeFunc see processBatch640 * @param function abortedFunc see processBatch641 * @return void642 */643 var scheduleBatch = function(processFunc, completeFunc, abortedFunc) {644 if (batchTimeout) {645 window.clearTimeout(batchTimeout);646 }647 var processBatchFunc = function() {648 processBatch.call(this, processFunc, completeFunc, abortedFunc);649 }650 batchTimeout = window.setTimeout(processBatchFunc.bind(this, processFunc, completeFunc, abortedFunc), iBatchGap);651 };652653 /**654 * Compare a batch of messages between two folders.655 *656 * @param nsIMsgFolder srcFolder657 * @param nsIMsgFolder destParent658 * @return void659 */660 var compareFolderBatch = function(srcFolder, destFolder) {661 if (srcFolderEnumerator === null) {662 try {663 srcFolder.updateFolder(null);664 srcFolder.getNewMessages(null,null);665 }666 catch( error ) {667 com.crunchmod.copyfolder.logError( "Error: " + srcFolder.name + " " + srcFolder.URI + " " + error );668 }669 iCompareFolderMissing = 0;670 srcFolderEnumerator = uniqueMsgEnumerator(srcFolder);671672 // Update the status and schedule a retry to prevent long running script warnings.673 com.crunchmod.copyfolder.setStatus('Comparing ' + folderPath(srcFolder) + ' messages...');674 scheduleBatch.call(this, compareFolderBatch, confirmDialog, null);675676 return false;677 }678679 if (destFolder !== null) {680 if (destFolderEnumerator === null) {681 destFolderEnumerator = uniqueMsgEnumerator(destFolder, true);682 }683684 // Pre load destination folder in batches to avoid stalls685 let batchCount = 0;686 let msgHdr;687 while (msgHdr = destFolderEnumerator.nextMsg()) {688 // nextMsg can process more than it returns so use the count as the batch increment689 batchCount += destFolderEnumerator.nextProcessedCnt();690 if (batchCount >= iCompareBatchMax) {691 com.crunchmod.copyfolder.setStatus('Comparing ' + folderPath(srcFolder) + ' loaded ' + destFolderEnumerator.msgCount() + ' target messages...');692 scheduleBatch.call(this, compareFolderBatch, confirmDialog, null);693694 return false;695 }696 }697 }698699 let batchCount = 0;700 let msgHdr;701 while (msgHdr = srcFolderEnumerator.nextMsg()) {702 // nextMsg can process more than it returns so use the count as the batch increment703 batchCount += srcFolderEnumerator.nextProcessedCnt();704 if (!messageExists(destFolder, msgHdr)) {705 iCompareFolderMissing++;706 }707708 if (batchCount >= iCompareBatchMax) {709 com.crunchmod.copyfolder.setStatus('Comparing ' + folderPath(srcFolder) + ' processed ' + srcFolderEnumerator.msgCount() + ' messages...');710 scheduleBatch.call(this, compareFolderBatch, confirmDialog, null);711712 return false;713 }714 }715716 let srcCnt = srcFolderEnumerator.msgTotal();717 let destCnt = (destFolder === null) ? 0 : destFolderEnumerator.msgTotal();718719 iDestTotalCount += destCnt;720 iSrcTotalCount += srcCnt;721 iSrcNewCount += iCompareFolderMissing;722723 com.crunchmod.copyfolder.logDebug(724 1,725 "folderCompare: folder: " + folderPath(srcFolder) +726 ", source: " + srcCnt +727 ", dest: " + destCnt +728 ", diff: " + (srcCnt - destCnt) +729 ", missing: " + iCompareFolderMissing +730 ", srcDups: " + srcFolderEnumerator.duplicateTotal() +731 ", destDups: " + ((destFolder === null) ? 0 : destFolderEnumerator.duplicateTotal())732 );733734 // Clean / reset out enumerators so we free up the memory735 srcFolderEnumerator = null;736 destFolderEnumerator = null;737738 return true;739 };740741 /**742 * Estimates messages in srcFolder that need to be tranfered to destFolder743 *744 * @param nsIMsgFolder srcFolder745 * @param nsIMsgFolder destParent746 * @return void747 */748 var estimateFolders = function(srcFolder, destParent) {749 // Build the folder tree750 iRef++;751 let destFolder;752 if (destParent === null || !destParent.containsChildNamed(srcFolder.prettyName)) {753 destFolder = null;754 } else {755 destFolder = destParent.getChildNamed(srcFolder.prettyName);756 }757 pendingFolders.push({srcFolder: srcFolder, destFolder: destFolder});758 if( destFolder != null )759 console.log("sizeOnDisk: " + decodeURI( destFolder.folderURL ) + " " + destFolder.sizeOnDisk);760761 if (srcFolder.hasSubFolders && bTreeCopy) {762 for (let subFolder of fixIterator(srcFolder.subFolders, Components.interfaces.nsIMsgFolder)) {763 estimateFolders.call(this, subFolder, destFolder);764 }765 }766767 iRef--;768 if (iRef != 0) {769 return;770 }771772 com.crunchmod.copyfolder.setStatus('Preparing to ' + actionVerb() + " " + iSrcNewCount + " messages...");773774 // Batch creation complete so kick off the compare.775 iRef++;776 processBatch.call(this, compareFolderBatch, confirmDialog, null);777 };778779 /**780 * Displays the user transfer confirmation dialog781 *782 * @return void783 */784 var confirmDialog = function() {785// let question = '';786 let question = new Array();787 if (iSrcNewCount > 0) {788// question = "<vbox><label><html:div>" + actionVerb(true) + " " + iSrcNewCount + " new messages from: <html:div style='padding:5px 10px; font-weight:bold;'>" +789// folderPath(oSrcFolder) +790// "</html:div> to: <html:div style='padding:5px 10px; font-weight:bold;'>" +791// folderPath(oDestParent, oSrcFolder) +792// "</html:div></html:div></label></vbox>";793 question[0] = 0;794 question[1] = actionVerb(true) + " " + iSrcNewCount;795 question[2] = folderPath(oSrcFolder);796 question[3] = folderPath(oDestParent, oSrcFolder);797 } else {798// question = "<vbox><label><html:div>There are no new messages to " + actionVerb() + ".</html:div></label></vbox>";799 question[0] = 1;800 question[1] = actionVerb();801 }802803// let warning = '';804 let warning = new Array();805 if (oDestParent.containsChildNamed(srcFolder.prettyName)) {806// warning = "<vbox><html:div style='margin: 0 3px 2px 3px; background: #3D9EFE; padding: 5px 10px; border: solid 1px #0A88FE; color: #FFF;'>The destination already contains a folder named \"<html:span style='font-weight: bold;'>" +807// oSrcFolder.prettyName +808// "</html:span>\"</html:div></vbox>";809 warning[0] = 0;810 warning[1] = oSrcFolder.prettyName;811 }812813 com.crunchmod.copyfolder.setStatus(null);814 com.crunchmod.copyfolder.logDebug(1, "confirmDialog: action: " + actionVerb(true) + ", iSrcTotalCount: " + iSrcTotalCount + ", iSrcNewCount: " + iSrcNewCount + ", iDestTotalCount: " + iDestTotalCount + ", diff: " + (iSrcTotalCount - iDestTotalCount));815816 params = {817 title: oSrcFolder.prettyName,818 srcFolderInfo: iSrcTotalCount + " messages" + ((iSrcNewCount != 0) ? (" (" + iSrcNewCount + " not in destination)") : ''),819 destFolderInfo: iDestTotalCount + ' messages',820 newMessages: iSrcNewCount,821 warning: warning,822 question: question,823 callback: com.crunchmod.copyfolder.dialog,824 };825826 window.openDialog("chrome://copyfolder/content/copyfolder-dialog.xul", "copyfolder-dialog", "chrome, dialog, centerscreen, modal", params).focus();827828 if (iSrcNewCount && params.ok) {829 process.call(this);830 }831 delete com.crunchmod.copyfolder.bRunning[oDestParent.URI];832 };833834 /**835 * Calculates the folder differences and the displays the transfer confirmation dialog.836 *837 * @return void838 */839 var calculateAndConfirm = function() {840 com.crunchmod.copyfolder.setStatus('Searching for new messages to ' + actionVerb() + '...');841 // Run the calculate after a small delay to allow the UI to update the status.842 var calculateFunc = function() {843 estimateFolders.call(this, oSrcFolder, oDestParent);844 };845 window.setTimeout(calculateFunc.bind(this), iBatchGap);846 };847848 /**849 * Sets progress bar percentage and displays the summary dialog if completed850 *851 * @param int Percent of messages copied relative to total messages in account.852 * @return void853 */854 var setProgress = function() {855 let processed = (iFailedCount + iSuccessCount);856 if (processed > iSrcNewCount) {857 iSrcNewCount = processed;858 }859 com.crunchmod.copyfolder.statusBar.setAttribute('collapsed', false);860 com.crunchmod.copyfolder.progressMeter.setAttribute('mode', 'normal');861 com.crunchmod.copyfolder.progressMeter.setAttribute('value', (processed / iSrcNewCount) * 100);862 com.crunchmod.copyfolder.setStatus('Processed ' + processed + ' of ' + iSrcNewCount + ' messages');863 checkDone.call(this);864 };865866867 /**868 * Transfers a messages from to destination folder.869 *870 * @param nsIMsgFolder destFolder Folder to transfer messages to.871 * @param nsIMsgDBHdr msgHdr message to transfer.872 * @return bool true if the transfer queued successfully false otherwise.873 */874 var transferMessage = function(destFolder, msgHdr) {875 let messages;876 try {877 messages = Components.classes['@mozilla.org/array;1'].createInstance(Components.interfaces.nsIMutableArray);878 messages.appendElement(msgHdr, false);879 // We use copyService as nsIMsgFolder.copyMessages doesn't trigger the OnStopCopy callback.880 copyService.CopyMessages(msgHdr.folder, messages, destFolder, bMove, copyListener(this, msgHdr, destFolder), null, false);881 } catch (ex) {882 com.crunchmod.copyfolder.logError(883 "CopyMessages call failed: msgHdr: " + msgHdr +884 ", folder:" + ((msgHdr) ? msgHdr.folder : 'N/A') +885 ", messages: " + messages +886 ", destFolder: " + destFolder +887 ", ex: " + ex888 );889 return false;890 }891892 iInflightCount++;893 inflightMsgs[msgHdr.messageId] = [destFolder, msgHdr];894 iCopyCount++;895 folderTotals.copies++;896897 return true;898 };899900 /**901 * Return the string key for the message transfer.902 *903 * @param nsIMsgDBHdr msgHdr message.904 * @param nsIMsgFolder destFolder for the message.905 * @return string906 */907 var transferKey = function(msgHdr, destFolder) {908 return folderPath(destFolder) + '/' + msgHdr.messageId;909 };910911 /**912 * Stores information about successful transfers.913 *914 * @param nsIMsgDBHdr msgHdr message to transfer.915 * @param nsIMsgFolder destFolder to transfer messages to.916 * @return void917 */918 var transferSuccess = function(msgHdr, destFolder) {919 let key = transferKey(msgHdr, destFolder);920 if (failedTransfers.hasOwnProperty(key)) {921 // Retry succeeded.922 delete failedTransfers[key];923 iFailedCount--;924 }925 iSuccessCount++;926 folderTotals.successes++;927 };928929 /**930 * Stores information about failed transfers, retrying it needed.931 *932 * @param nsIMsgDBHdr msgHdr message to transfer.933 * @param nsIMsgFolder destFolder Folder to transfer messages to.934 * @return void935 */936 var transferFailed = function(msgHdr, destFolder, status) {937 let key = transferKey(msgHdr, destFolder);938 let failure;939 if (failedTransfers.hasOwnProperty(key)) {940 failure = failedTransfers[key];941 failure.failed++;942 } else {943 failure = {944 msgHdr: msgHdr,945 destFolder: destFolder,946 failed: 1947 };948 failedTransfers[key] = failure;949 iFailedCount++;950 }951 folderTotals.failures++;952953 let msg = "Failed to " + actionVerb() + " message (error code: " + status + ")\n" +954 "subject: " + msgHdr.subject + "\n" +955 "messageKey: " + msgHdr.messageKey + "\n" +956 "messageId: " + msgHdr.messageId + "\n" +957 "folder: " + folderPath(msgHdr.folder)958959 if (failure.failed < iMaxRetries) {960 folderTotals.retries++;961 com.crunchmod.copyfolder.logWarn(msg + "\nretrying...");962 transferMessage.call(this, destFolder, msgHdr);963 } else {964 com.crunchmod.copyfolder.logError(msg);965 }966 };967968 /*969 * Provides nsIMsgCopyServiceListener interface methods for copy notifications.970 */971 var copyListener = function(aTransfer, aMsgHdr, aDestFolder) {972 var transfer = aTransfer;973 var msgHdr = aMsgHdr;974 var destFolder = aDestFolder;975976 return {977 OnStartCopy: function() {978 dLastTransferCallback = new Date();979 },980 OnProgress: function(aProgress, aProgressMax) {981 dLastTransferCallback = new Date();982 },983 SetMessageKey: function(aKey) {},984 GetMessageId: function(aMessageId) {},985 OnStopCopy: function(aStatus) {986 dLastTransferCallback = new Date();987 iInflightCount--;988 delete inflightMsgs[msgHdr.messageId];989 if (Components.isSuccessCode(aStatus)) {990 transferSuccess.call(transfer, msgHdr, destFolder);991 console.log("gds: xfer good");992 } else {993 console.log("gds: xfer failed");994 transferFailed.call(transfer, msgHdr, destFolder, aStatus);995 }996 setProgress.call(transfer);997 if (iRef != 0 && iInflightCount <= iInflightMin && !bAborted) {998 processBatch.call(transfer, transferFolderBatch, checkDone, checkDone);999 }1000 dLastTransferCallbackComplete = new Date();1001 // If we got here we have potentially recovered from a stall so clear our retried flag.1002 bRetried = false;1003 }1004 }1005 };10061007 /**1008 * Returns a folder message enumerator that only returns unique messages according to messageHashCode.1009 *1010 * @param nsIMsgFolder aFolder Folder to iterate over.1011 * @return uniqueMsgEnumerator1012 */1013 var uniqueMsgEnumerator = function(aFolder, bDateless) {1014 var msgEnumerator = null;1015 var seenHashCodes = {};1016 var dateless = bDateless1017 var msgCnt = 0;1018 var duplicates = 0;1019 var getNextProcessedCnt = 0;10201021 // nsIMsgFolder.messages can throw exceptions e.g. error: 0x80550005 (NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)1022 // if it does so catch it, inform the user and abort as the results would be invalid if we let it continue1023 try {1024 msgEnumerator = aFolder.messages;1025 } catch (ex) {1026 let msg = 'Failed get messages from: ' + folderPath(aFolder)+ ' aborting!';1027 com.crunchmod.copyfolder.setStatus(msg);1028 com.crunchmod.copyfolder.logError(msg);1029 alert(msg);10301031 com.crunchmod.copyfolder.setStatus(null);1032 com.crunchmod.copyfolder.statusBar.setAttribute('collapsed', true);10331034 // Flag aborted in case we have any scheduled timeouts.1035 abortTransfer();10361037 throw ex;1038 }10391040 var getNext = function() {1041 getNextProcessedCnt = 0;1042 while (msgEnumerator.hasMoreElements()) {1043 getNextProcessedCnt++;1044 let msgHdr = msgEnumerator.getNext().QueryInterface(Components.interfaces.nsIMsgDBHdr);1045 let hashCode = messageHashCode(msgHdr, true);1046 if (!seenHashCodes.hasOwnProperty(hashCode)) {1047 let detail = {msgHdr: msgHdr, hashCode: hashCode, datelessHashCode: null};1048 seenHashCodes[hashCode] = true1049 if (dateless) {1050 let datelessHashCode = messageHashCode(msgHdr, false);1051 if (seenHashCodes.hasOwnProperty(datelessHashCode)) {1052 seenHashCodes[datelessHashCode] = false;1053 } else {1054 seenHashCodes[datelessHashCode] = true;1055 }1056 detail.datelessHashCode = datelessHashCode;1057 }10581059 if (hasMd5Id(msgHdr)) {1060 // md5 hashes are location specific so don't bother checking it1061 msgCnt++;1062 return detail;1063 }10641065 var messageIdHashCode = murmurhash3(msgHdr.messageId, iHashSeed);1066 if (!seenHashCodes.hasOwnProperty(messageIdHashCode)) {1067 seenHashCodes[messageIdHashCode] = true;1068 msgCnt++;1069 return detail;1070 }1071 } else {1072 duplicates++;1073 }1074 }10751076 return null;1077 };10781079 var nextMsg = function() {1080 let aMsgDetail = getNext();1081 if (aMsgDetail === null) {1082 return null;1083 }10841085 return aMsgDetail.msgHdr;1086 };10871088 var msgExists = function(aMsgHdr) {1089 enumerate();1090 if (msgCnt === 0) {1091 return false;1092 }10931094 if (seenHashCodes.hasOwnProperty(messageHashCode(aMsgHdr, true))) {1095 return true;1096 }10971098 if (!dateless) {1099 return false;1100 }11011102 let datelessHashCode = messageHashCode(aMsgHdr, false);1103 if (seenHashCodes.hasOwnProperty(datelessHashCode)) {1104 return seenHashCodes[datelessHashCode];1105 }11061107 return false;1108 };11091110 var enumerate = function() {1111 while (getNext()) {1112 }1113 };11141115 var msgCount = function() {1116 return msgCnt;1117 };11181119 var msgTotal = function() {1120 enumerate();1121 return msgCnt;1122 };11231124 var duplicateTotal = function() {1125 enumerate();1126 return duplicates;1127 };11281129 var nextProcessedCnt = function() {1130 return getNextProcessedCnt;1131 };11321133 return {1134 getNext: getNext,1135 nextMsg: nextMsg,1136 msgExists: msgExists,1137 msgCount: msgCount,1138 msgTotal: msgTotal,1139 enumerate: enumerate,1140 duplicateTotal: duplicateTotal,1141 nextProcessedCnt: nextProcessedCnt1142 }1143 }11441145 /**1146 * Transfers a batch of messages from source folder to destination folder.1147 *1148 * @param nsIMsgFolder srcFolder Folder to transfer messages from.1149 * @param nsIMsgFolder destFolder Folder to transfer messages to.1150 * @return bool true if we completed this folder, false if there is more to go1151 */1152 var transferFolderBatch = function(srcFolder, destFolder) {1153 if (srcFolderEnumerator === null) {1154 srcFolderEnumerator = uniqueMsgEnumerator(srcFolder);1155 }1156 if (destFolderEnumerator === null) {1157 destFolderEnumerator = uniqueMsgEnumerator(destFolder, true);1158 }1159 destFolder.updateSummaryTotals(true);11601161 // Pre load destination folder in batches to avoid stalls1162 let batchCount = 0;1163 let msgHdr;1164 while (msgHdr = destFolderEnumerator.nextMsg()) {1165 // nextMsg can process more than it returns so use the count as the batch increment1166 batchCount += destFolderEnumerator.nextProcessedCnt();1167 if (batchCount >= iCompareBatchMax) {1168 com.crunchmod.copyfolder.setStatus('Transfer ' + folderPath(srcFolder) + ' loaded ' + destFolderEnumerator.msgCount() + ' target messages...');1169 scheduleBatch.call(this, transferFolderBatch, checkDone);11701171 return false;1172 }1173 }11741175 batchCount = 0;1176 while ((msgHdr = srcFolderEnumerator.nextMsg()) && !bAborted) {1177 batchCount += srcFolderEnumerator.nextProcessedCnt();1178 if (folderWasCreated(destFolder) || !messageExists(destFolder, msgHdr)) {1179 transferMessage.call(this, destFolder, msgHdr);11801181 if (iInflightCount == iInflightMax) {1182 // Reached the max inflight so return1183 return false;1184 }1185 }11861187 if (batchCount >= iCompareBatchMax) {1188 // Prevent timeout when processing folders with lots of existing messages.1189 com.crunchmod.copyfolder.setStatus('Transfer ' + folderPath(srcFolder) + ' checked ' + destFolderEnumerator.msgCount() + ' messages...');1190 scheduleBatch.call(this, transferFolderBatch, checkDone);11911192 return false;1193 }1194 }11951196 com.crunchmod.copyfolder.logInfo(1197 "transferFolderBatch: folder: " + folderPath(destFolder) +1198 ", successes: " + folderTotals.successes +1199 ", failures: " + folderTotals.failures +1200 ", copies: " + folderTotals.copies +1201 ", retries: " + folderTotals.retries +1202 ", expected: " + srcFolderEnumerator.msgTotal() +1203 ", inflight: " + iInflightCount +1204 ", bAborted: " + bAborted +1205 ", have (so far): " + folderMessageCount(destFolder, false)1206 );12071208 folderTotals.failures = 0;1209 folderTotals.successes = 0;1210 folderTotals.copies = 0;1211 folderTotals.retries = 0;12121213 // clean out hash codes cache1214 srcFolderEnumerator = null;1215 destFolderEnumerator = null12161217 try {1218 // Update the folder so hopefully if the user runs a second time they get the right results.1219 // TODO(steve): make this a configable option as doing it by default can cause the TB to become1220 // really unresponsive.1221 //destFolder.setFlag(Components.interfaces.nsMsgFolderFlags.CheckNew);1222 destFolder.updateFolder(null);1223 // Force update summary totals from db too.1224 destFolder.updateSummaryTotals(true);1225 } catch (ex) {1226 com.crunchmod.copyfolder.logError("Failed to update " + folderPath(updateFolder) + ": " + ex);1227 }12281229 return true;1230 };12311232 /**1233 * Flag the transfer as aborted and cleanup1234 *1235 * @return void1236 */1237 var abortTransfer = function() {1238 bAborted = true;1239 window.clearInterval(transferWatchdogInterval);1240 }12411242 /**1243 * Displays the summary dialog if completed and collapses the statuses areas1244 *1245 * @return void1246 */1247 var transferWatchdog = function() {1248 let now = new Date();1249 let timeDiff = now.getTime() - dLastTransferCallback.getTime();1250 if (timeDiff > iTransferWatchdogWarning) {1251 let errMsg = "No transfer callback since: last: " + dLastTransferCallback.toUTCString() +1252 ", diff: " + timeDiff +1253 ", now: " + now.toUTCString() +1254 ", last complete: " + dLastTransferCallback.toUTCString() +1255 ", iRef: " + iRef +1256 ", iInflightCount: " + iInflightCount +1257 ", iSuccessCount: " + iSuccessCount +1258 ", iFailedCount: " + iFailedCount;12591260 if (timeDiff > iTransferWatchdogAbort) {1261 // Unfortunately it seems like the nsIMsgCopyService does just stop responding or at1262 // least stops calling the nsIMsgCopyServiceListener function.1263 //1264 // At this point we've already retried so there's nothing more we can do :(1265 com.crunchmod.copyfolder.logError(errMsg + " aborting...");1266 iFailedCount = iSrcNewCount - iSuccessCount;1267 abortTransfer();1268 checkDone.call(this);1269 } else if (timeDiff > iTransferWatchdogRetry && !bRetried) {1270 com.crunchmod.copyfolder.logError(errMsg + " retrying...");12711272 // Retry the inflight transfers to see if it fixes the stall.1273 var inflightCopy = {};1274 for (let key in inflightMsgs) {1275 inflightCopy[key] = inflightMsgs[key];1276 }1277 inflightMsgs = {};1278 iInflightCount = 0;12791280 for (let key in inflightCopy) {1281 var entry = inflightCopy[key];1282 if (!transferMessage.call(this, entry[0], entry[1]) && bAborted) {1283 break;1284 }1285 }1286 bRetried = true;1287 } else {1288 com.crunchmod.copyfolder.logError(errMsg);1289 }1290 }1291 };12921293 /**1294 * Displays the summary dialog if completed and collapses the statuses areas1295 *1296 * @return void1297 */1298 var checkDone = function() {1299 if ((iRef != 0 || iInflightCount != 0) && !bAborted) {1300 return;1301 }13021303 window.clearInterval(transferWatchdogInterval);1304 notifyService.removeListener(this);13051306 let status = '<html:img src="chrome://copyfolder/skin/images/success.png" style="vertical-align: bottom;" /> Success';1307 let summary = successVerb(true) + ' ' + iSuccessCount + ' message(s) successfully';13081309 if (iFailedCount) {1310 summary += ', failed ' + iFailedCount + ' message(s)';1311 }13121313// let summaryDisplay = summary + ' from: <html:div style="padding:5px 10px; font-weight:bold;">' + folderPath(oSrcFolder) +1314// '</html:div> to: <html:div style="padding:5px 10px; font-weight:bold;">' + folderPath(oDestParent, oSrcFolder) +1315// '</html:div>';1316 summaryDisplay = new Array();1317 summaryDisplay[0] = 0;1318 summaryDisplay[1] = summary;1319 summaryDisplay[2] = folderPath(oSrcFolder);1320 summaryDisplay[3] = folderPath(oDestParent, oSrcFolder);13211322 summary += ' from: ' + folderPath(oSrcFolder) + ' to: ' + folderPath(oDestParent, oSrcFolder);13231324 if (bAborted) {1325 summary += " ABORTED!";1326 summaryDisplay[3] += " ABORTED!";1327 }13281329 com.crunchmod.copyfolder.setStatus(summary);1330 com.crunchmod.copyfolder.logInfo(summary);13311332 window.openDialog(1333 "chrome://copyfolder/content/copyfolder-summary.xul",1334 "copyfolder-summary",1335 "chrome, dialog, modal, centerscreen",1336 {status: status, summary: summaryDisplay}1337 ).focus();13381339 com.crunchmod.copyfolder.setStatus(null);1340 com.crunchmod.copyfolder.statusBar.setAttribute('collapsed', true);1341 };13421343 /**1344 * Creates a folder in the destination.1345 *1346 * @param nsIMsgFolder srcFolder Folder to copy messages from.1347 * @param nsIMsgFolder destParent Parent of where destination folder will be created.1348 * @return void1349 */1350 var createFolder = function(aSrcFolder, aDestParent) {1351 let path = folderPath(aDestParent, aSrcFolder);1352 com.crunchmod.copyfolder.logDebug(2, "createFolder: path: " + path);1353 pendingFolderCreates[path] = {srcFolder: aSrcFolder, destParent: aDestParent};1354 aDestParent.createSubfolder(aSrcFolder.prettyName, null);1355 };13561357 /**1358 * Notified after a folder has been added via nsIMsgFolderNotificationService.1359 *1360 * @param aFolder The folder that has just been added1361 * @return void1362 */1363 var folderAdded = function(aFolder) {1364 let path = folderPath(aFolder);1365 // Check that this is the folder we're interested in.1366 if (pendingFolderCreates.hasOwnProperty(path)) {1367 let aCreateFolder = pendingFolderCreates[path];1368 delete pendingFolderCreates[path];1369 // We use URI instead of path here to speed up the check by folderWasCreated.1370 createdFolders[aFolder.URI] = true;1371 iRef--;1372 transferFolders.call(this, aCreateFolder.srcFolder, aCreateFolder.destParent);1373 }1374 };13751376 /**1377 * Returns true if we created this folder during the this transfer.1378 *1379 * @param aFolder The folder to check1380 * @return bool1381 */1382 var folderWasCreated = function(aFolder) {1383 return createdFolders.hasOwnProperty(aFolder.URI);1384 };13851386 /**1387 * Iterates over the pending folder pairs, calling the passed function.1388 *1389 * @param function processFunc the function to call on each folder pair1390 * @param function completeFunc the function to call after all pairs have been processed1391 * @param function abortedFunc the function to call if processing is aborted1392 * @return void1393 */1394 var processBatch = function(processFunc, completeFunc, abortedFunc) {1395 while (pendingFolders.length != 0 && !bAborted) {1396 let folders = pendingFolders[0];1397 if (!processFunc.call(this, folders.srcFolder, folders.destFolder)) {1398 // still more to go1399 return;1400 }1401 pendingFolders.splice(0, 1);1402 }1403 iRef--;14041405 if (bAborted) {1406 pendingFolders = [];1407 if (abortedFunc !== null) {1408 abortedFunc.call(this);1409 }1410 return;1411 }14121413 if (completeFunc !== null) {1414 completeFunc.call(this);1415 }1416 };14171418 /**1419 * Builds the list of folders to transfer ensuring all destination folders exist and then transfers them.1420 *1421 * @param nsIMsgFolder srcFolder Folder to create from.1422 * @param nsIMsgFolder destParent Parent of where destination folders will be created.1423 * @return void1424 */1425 var transferFolders = function(srcFolder, destParent) {1426 com.crunchmod.copyfolder.logDebug(2, "transferFolders: " + folderPath(srcFolder) + ", destParent: " + folderPath(destParent));1427 iRef++;1428 if (!destParent.containsChildNamed(srcFolder.prettyName)) {1429 // transferFolders will continue when the folder creation notification (folderAdded) fires.1430 createFolder(srcFolder, destParent);1431 return;1432 }14331434 let destFolder = destParent.getChildNamed(srcFolder.prettyName);1435 pendingFolders.push({srcFolder: srcFolder, destFolder: destFolder});14361437 if (srcFolder.hasSubFolders && bTreeCopy) {1438 for (let subFolder of fixIterator(srcFolder.subFolders, Components.interfaces.nsIMsgFolder)) {1439 transferFolders.call(this, subFolder, destFolder);1440 }1441 }1442 iRef--;1443 if (iRef != 0) {1444 return;1445 }14461447 com.crunchmod.copyfolder.setStatus('Preparing to ' + actionVerb() + " " + iSrcNewCount + " messages...");14481449 // Batch creation complete so kick off the transfer.1450 iRef++;1451 var transferWatchdogFunc = function() {1452 transferWatchdog.call(this);1453 }1454 transferWatchdogInterval = window.setInterval(transferWatchdogFunc.bind(this), 30000);1455 dLastTransferCallback = new Date();1456 dLastTransferCallbackComplete = new Date();1457 processBatch.call(this, transferFolderBatch, checkDone, checkDone);1458 };14591460 /**1461 * Processes the transfer1462 *1463 * @return void1464 */1465 var process = function() {1466 com.crunchmod.copyfolder.setStatus('Processing ' + actionVerb() + " between " + folderPath(oSrcFolder) + " and " + folderPath(oDestParent) + "...");1467 copyService = Components.classes['@mozilla.org/messenger/messagecopyservice;1'].getService(Components.interfaces.nsIMsgCopyService);14681469 notifyService = Components.classes["@mozilla.org/messenger/msgnotificationservice;1"].getService(Components.interfaces.nsIMsgFolderNotificationService);1470 notifyService.addListener(this, notifyService.folderAdded);14711472 com.crunchmod.copyfolder.setStatus('Creating missing destination folders...');1473 transferFolders.call(this, oSrcFolder, oDestParent);14741475 // Call done dialog in case we processed really quickly1476 checkDone.call(this);1477 };14781479 return {1480 calculateAndConfirm: calculateAndConfirm,1481 folderAdded: folderAdded1482 };1483 },1484 dialog: function(document, args) {1485 var srcFolderInfo = document.getElementById("srcFolderInfo");1486 var destFolderInfo = document.getElementById("destFolderInfo");14871488 srcFolderInfo.value = args.srcFolderInfo;1489 destFolderInfo.value = args.destFolderInfo;1490 if(args.newMessages == 0) {1491 document.documentElement.getButton("accept").style.visibility = 'hidden';1492 document.documentElement.getButton("cancel").label = 'Ok';1493 } else {1494 document.documentElement.getButton("accept").style.visibility = 'visible';1495 document.documentElement.getButton("cancel").label = 'Cancel';1496 }1497 document.getElementById("copyfolder-dialog").setAttribute("title", args.title + " - Copy Folder");1498 //document.getElementById("warning").innerHTML = args.warning;1499 //document.getElementById("question").innerHTML = args.question;1500 if( args.warning.length == 0 ) {1501 document.getElementById("warning").style.visibility = 'hidden';1502 } else {1503 document.getElementById("warning0").textContent = args.warning[1];1504 }1505 if( args.question.length == 0 ) {1506 document.getElementById("question0").style.visibility = 'hidden';1507 document.getElementById("question1").style.visibility = 'hidden';1508 } else {1509 switch( args.question[0] ) {1510 case 0:1511 document.getElementById("question1").style.visibility = 'hidden';1512 document.getElementById("question01").textContent = args.question[1];1513 document.getElementById("question02").textContent = args.question[2];1514 document.getElementById("question03").textContent = args.question[3];1515 break;1516 case 1:1517 document.getElementById("question0").style.visibility = 'hidden';1518 document.getElementById("question11").textContent = args.question[1];1519 break;1520 }1521 }1522 },1523};1524 ...

Full Screen

Full Screen

postinstall.js

Source:postinstall.js Github

copy

Full Screen

1const fs = require("fs-extra");2var productName3var xtype4var xtypeFileName5function doXtype() {6 fs.copySync(`../ext-web-components-${xtype}/ext-runtime/${xtypeFileName}`,`../../../${copyFolder}ext-runtime/${xtypeFileName}`);7 console.log(`${prefix} ${xtypeFileName} copied to ./${copyFolder}ext-runtime`);8}9var packageNameThis = './package.json';10var packageThis = fs.readFileSync(packageNameThis, 'utf8');11const packageJsonThis = JSON.parse(packageThis);12function boldGreen (s) {13 var boldgreencolor = `\x1b[32m\x1b[1m`14 var endMarker = `\x1b[0m`15 return (`${boldgreencolor}${s}${endMarker}`)16}17var prefix =(`${boldGreen(packageJsonThis.name + ':')}`)18var dashCount = (packageJsonThis.name.match(/-/g) || []).length;19if (dashCount == 2) {20 var last = packageJsonThis.name.lastIndexOf('-');21 productName = packageJsonThis.name.substring(0,last);22 xtype = packageJsonThis.name.substring(productName.length+1);23 xtypeFileName = `ext.${xtype}.js`;24}25else {26 productName = packageJsonThis.name;27 xtype = '';28 xtypeFileName = ``;29}30var copyFolder = '';31switch(productName) {32 case '@sencha/ext-react':33 copyFolder = 'public/';34 if (!fs.existsSync(`../../../${copyFolder}index.html`)) {35 console.log(`${prefix} ./${copyFolder}index.html does not exist, not creating ext-runtime folder`);36 return37 }38 break;39 case '@sencha/ext-angular':40 copyFolder = '';41 if (!fs.existsSync('../../../angular.json')) {42 console.log(`${prefix} ./angular.json does not exist, not creating ext-runtime folder`);43 return44 }45 break;46 default:47 copyFolder = '';48}49if (fs.existsSync(`../../../${copyFolder}ext-runtime`)) {50 console.log(`${prefix} ./${copyFolder}ext-runtime exists`);51 if (xtype != '') {doXtype()}52 console.log('');53 return54}55const packageJsonApp = JSON.parse(fs.readFileSync(`../../../package.json`, 'utf8'));56if (packageJsonApp.dependencies != undefined) {57 var dependencies = packageJsonApp.dependencies['@sencha/ext-webpack-plugin'];58 if (dependencies != undefined) {59 console.log(`${prefix} @sencha/ext-webpack-plugin is defined, not creating ext-runtime folder`);60 return61 }62}63if (packageJsonApp.devDependencies != undefined) {64 var devDependencies = packageJsonApp.devDependencies['@sencha/ext-webpack-plugin'];65 if (devDependencies != undefined) {66 console.log(`${prefix} @sencha/ext-webpack-plugin is defined, not creating ext-runtime folder`);67 return68 }69}70if (fs.existsSync('../../../webpack.config.js')) {71 console.log(`${prefix} ./webpack.config.js exists, not creating ext-runtime folder`);72 return73}74try {75 var theme;76 if(packageJsonApp.extTheme != undefined) {77 var themes = ['material', 'neptune'];78 if(themes.includes(packageJsonApp.extTheme)) {79 theme = packageJsonApp.extTheme;80 console.log(`${prefix} "extTheme": ${theme} found in ./package.json`);81 }82 else {83 theme = 'material';84 }85 }86 else {87 theme = 'material';88 }89 fs.copySync(`../ext-runtime-base/theme/${theme}`,`../../../${copyFolder}ext-runtime/theme/${theme}`);90 console.log(`${prefix} created ./${copyFolder}ext-runtime/theme/${theme} folder`);91 fs.copySync('../ext-runtime-base/engine.js',`../../../${copyFolder}ext-runtime/engine.js`);92 console.log(`${prefix} created ./${copyFolder}ext-runtime/engine.js`);93 switch(productName) {94 case '@sencha/ext-react':95 var indexHtml = fs.readFileSync(`../../../${copyFolder}index.html`, 'utf8');96 //var position = indexHtml.indexOf('<title>');97 var position = indexHtml.indexOf('</head>');98 var styles = `99 <!--https://www.rapidtables.com/web/color/-->100 <style>101 :root {102 --base-color: #024059;103 --base-foreground-color: white;104 --background-color: white;105 --color: black;106 }107 </style>108 `109 var b =110 `111 <link112 href="%PUBLIC_URL%/ext-runtime/theme/${theme}/${theme}-all.css"113 rel="stylesheet" type="text/css"114 >115 <script src="%PUBLIC_URL%/ext-runtime/engine.js"></script>116${styles}117 `118 fs.copySync(`../../../${copyFolder}index.html`,`../../../${copyFolder}indexBack.html`);119 var indexHtmlNew = indexHtml.substring(0, position) + b + indexHtml.substring(position);120 fs.writeFileSync(`../../../${copyFolder}index.html`, indexHtmlNew);121 console.log(`${prefix} updated ./${copyFolder}index.html`);122 console.log(`${prefix} backup in ./${copyFolder}indexBack.html`);123 break;124 case '@sencha/ext-angular':125 var angularName = '../../../angular.json';126 var angular = fs.readFileSync(angularName, 'utf8');127 const angularJson = JSON.parse(angular);128 var style = `ext-runtime/theme/${theme}/${theme}-all.css`;129 var script = "ext-runtime/engine.js";130 angularJson.projects[packageJsonApp.name].architect.build.options.styles.push(style);131 angularJson.projects[packageJsonApp.name].architect.build.options.scripts.push(script);132 const angularString = JSON.stringify(angularJson, null, 2);133 fs.writeFileSync(angularName, angularString);134 console.log(`${prefix} added ${style} to styles array in ./angular.json`);135 console.log(`${prefix} added ${script} to scripts array in ./angular.json`);136 break;137 default:138 }139 if (xtype != '') {doXtype()}140}...

Full Screen

Full Screen

copyfolder-common.js

Source:copyfolder-common.js Github

copy

Full Screen

1var EXPORTED_SYMBOLS = ["CopyFolder"];2const Cc = Components.classes;3const Ci = Components.interfaces;4if ("undefined" == typeof(messenger)) {5 var messenger = Cc["@mozilla.org/messenger;1"].createInstance(Ci.nsIMessenger);6}7var CopyFolder = {};8// Preferences9// -----------10CopyFolder.Prefs = {11 // const12 preferencePrefix : "extensions.copyfolder.",13 _prefService: null,14 get prefService()15 {16 if (!this._prefService)17 this._prefService =18 Components.classes["@mozilla.org/preferences-service;1"]19 .getService(Components.interfaces.nsIPrefBranch);20 return this._prefService;21 },22 getBoolPref: function(prefName, defaultValue) {23 try {24 return this.prefService.getBoolPref(25 CopyFolder.Prefs.preferencePrefix + prefName);26 } catch(ex) {27 if (defaultValue != undefined)28 return defaultValue;29 throw(ex);30 }31 },32 getCharPref: function(prefName, defaultValue) {33 try {34 return this.prefService.getCharPref(35 CopyFolder.Prefs.preferencePrefix + prefName);36 } catch(ex) {37 if (defaultValue) {38 return defaultValue;39 }40 throw(ex);41 }42 },43 getIntPref: function(prefName, defaultValue) {44 try {45 return this.prefService.getIntPref(46 CopyFolder.Prefs.preferencePrefix + prefName);47 } catch(ex) {48 if (defaultValue)49 return defaultValue;50 throw(ex);51 }52 },53 getLocalizedStringPref: function(prefName, defaultValue) {54 try {55 return this.prefService56 .getComplexValue(57 CopyFolder.Prefs.preferencePrefix +58 prefName,Components.interfaces.nsIPrefLocalizedString).data;59 } catch(ex) {60 if (defaultValue) {61 return defaultValue;62 }63 throw(ex);64 }65 },66 setBoolPref: function(prefName, val) {67 this.prefService.setBoolPref(68 CopyFolder.Prefs.preferencePrefix + prefName, val);69 },70 setCharPref: function(prefName, val) {71 this.prefService.setCharPref(72 CopyFolder.Prefs.preferencePrefix + prefName, val);73 },74 setIntPref: function(prefName, val) {75 this.prefService.setIntPref(76 CopyFolder.Prefs.preferencePrefix + prefName, val);77 },78 setAppStringPref: function(appPrefName, str) {79 if (BiDiMailUI.App.versionIsAtLeast("58.0b1")) {80 BiDiMailUI.Prefs.prefService.setStringPref(appPrefName, str);81 }82 else83 {84 BiDiMailUI.Prefs.prefService.setComplexValue(85 appPrefName, Components.interfaces.nsISupportsString, str);86 }87 },88 setLocalizedStringPref: function (prefName, val) {89 var pls =90 Components.classes["@mozilla.org/pref-localizedstring;1"]91 .createInstance(Components.interfaces.nsIPrefLocalizedString);92 pls.data = val;93 setAppStringPref(CopyFolder.Prefs.preferencePrefix +94 prefName, pls);95 }...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1import { copyFolder } from 'ts-auto-mock';2copyFolder('src', 'dist');3import { copyFolder } from 'ts-auto-mock';4copyFolder('src', 'dist');5import { copyFolder } from 'ts-auto-mock';6copyFolder('src', 'dist');7import { copyFolder } from 'ts-auto-mock';8copyFolder('src', 'dist');9import { copyFolder } from 'ts-auto-mock';10copyFolder('src', 'dist');11import { copyFolder } from 'ts-auto-mock';12copyFolder('src', 'dist');13import { copyFolder } from 'ts-auto-mock';14copyFolder('src', 'dist');15import { copyFolder } from 'ts-auto-mock';16copyFolder('src', 'dist');17import { copyFolder } from 'ts-auto-mock';18copyFolder('src', 'dist');19import { copyFolder } from 'ts-auto-mock';20copyFolder('src', 'dist');21import { copyFolder } from 'ts-auto-mock';22copyFolder('src', 'dist');23import { copyFolder } from 'ts-auto-mock';24copyFolder('src', 'dist');25import { copyFolder } from 'ts-auto-mock';26copyFolder('src', '

Full Screen

Using AI Code Generation

copy

Full Screen

1const tsAutoMock = require('ts-auto-mock');2tsAutoMock.copyFolder('src', 'dist');3const tsAutoMock = require('ts-auto-mock');4tsAutoMock.copyFolder('src', 'dist');5const tsAutoMock = require('ts-auto-mock');6tsAutoMock.copyFolder('src', 'dist');7const tsAutoMock = require('ts-auto-mock');8tsAutoMock.copyFolder('src', 'dist');9const tsAutoMock = require('ts-auto-mock');10tsAutoMock.copyFolder('src', 'dist');11const tsAutoMock = require('ts-auto-mock');12tsAutoMock.copyFolder('src', 'dist');13const tsAutoMock = require('ts-auto-mock');14tsAutoMock.copyFolder('src', 'dist');15const tsAutoMock = require('ts-auto-mock');16tsAutoMock.copyFolder('src', 'dist');17const tsAutoMock = require('ts-auto-mock');18tsAutoMock.copyFolder('src', 'dist');19const tsAutoMock = require('ts-auto-mock');20tsAutoMock.copyFolder('src', 'dist');21const tsAutoMock = require('ts-auto-mock');22tsAutoMock.copyFolder('src', 'dist');23const tsAutoMock = require('ts-auto-mock');24tsAutoMock.copyFolder('src', 'dist');

Full Screen

Using AI Code Generation

copy

Full Screen

1const tsAutoMock = require('ts-auto-mock');2tsAutoMock.copyFolder('./src', './dist');3const tsAutoMock = require('ts-auto-mock');4tsAutoMock.copyFolder('./src', './dist', { 5});6const tsAutoMock = require('ts-auto-mock');7tsAutoMock.copyFolder('./src', './dist', { 8}, (err, files) => {9 if (err) {10 console.log('Error while copying files', err);11 return;12 }13 console.log('Files copied successfully', files);14});15const tsAutoMock = require('ts-auto-mock');16tsAutoMock.copyFolder('./src', './dist', { 17}, (err, files) => {18 if (err) {19 console.log('Error while copying files', err);20 return;21 }22 console.log('Files copied successfully', files);23}, true);24const tsAutoMock = require('ts-auto-mock');25tsAutoMock.copyFolder('./src', './dist', { 26}, (err, files) => {27 if (err) {28 console.log('Error while copying files', err);29 return;30 }31 console.log('Files copied successfully', files);32}, false);33const tsAutoMock = require('ts-auto-mock');34tsAutoMock.copyFolder('./src', './dist', {

Full Screen

Using AI Code Generation

copy

Full Screen

1import { copyFolder } from 'ts-auto-mock';2import * as path from 'path';3const sourcePath = path.resolve(__dirname, 'src');4const destinationPath = path.resolve(__dirname, 'dist');5copyFolder(sourcePath, destinationPath);6import { copyFile } from 'ts-auto-mock';7import * as path from 'path';8const sourcePath = path.resolve(__dirname, 'src', 'file.ts');9const destinationPath = path.resolve(__dirname, 'dist', 'file.ts');10copyFile(sourcePath, destinationPath);11import { copyFile } from 'ts-auto-mock';12import * as path from 'path';13const sourcePath = path.resolve(__dirname, 'src', 'file.ts');14const destinationPath = path.resolve(__dirname, 'dist', 'file.ts');15copyFile(sourcePath, destinationPath, { overwrite: true });16import { copyFile } from 'ts-auto-mock';17import * as path from 'path';18const sourcePath = path.resolve(__dirname, 'src', 'file.ts');19const destinationPath = path.resolve(__dirname, 'dist', 'file.ts');20copyFile(sourcePath, destinationPath, { overwrite: false });

Full Screen

Using AI Code Generation

copy

Full Screen

1const { copyFolder } = require('ts-auto-mock');2copyFolder('src', 'mocks');3const { copyFolder } = require('ts-auto-mock');4copyFolder('src', 'mocks');5const { copyFolder } = require('ts-auto-mock');6copyFolder('src', 'mocks');7const { copyFolder } = require('ts-auto-mock');8copyFolder('src', 'mocks');9const { copyFolder } = require('ts-auto-mock');10copyFolder('src', 'mocks');11const { copyFolder } = require('ts-auto-mock');12copyFolder('src', 'mocks');13const { copyFolder } = require('ts-auto-mock');14copyFolder('src', 'mocks');15const { copyFolder } = require('ts-auto-mock');16copyFolder('src', 'mocks');17const { copyFolder } = require('ts-auto-mock');18copyFolder('src', 'mocks');19const { copyFolder } = require('ts-auto-mock');20copyFolder('src', 'mocks');21const { copyFolder } = require('ts-auto-mock');22copyFolder('src', 'mocks');23const { copyFolder } = require('ts-auto-mock');24copyFolder('src', 'mocks');

Full Screen

Using AI Code Generation

copy

Full Screen

1import {copyFolder} from 'ts-auto-mock';2copyFolder('src', 'dist');3import {copyFolder} from 'ts-auto-mock';4copyFolder('src', 'dist');5import {copyFolder} from 'ts-auto-mock';6copyFolder('src', 'dist');7import {copyFolder} from 'ts-auto-mock';8copyFolder('src', 'dist');9import {copyFolder} from 'ts-auto-mock';10copyFolder('src', 'dist');11import {copyFolder} from 'ts-auto-mock';12copyFolder('src', 'dist');13import {copyFolder} from 'ts-auto-mock';14copyFolder('src', 'dist');15import {copyFolder} from 'ts-auto-mock';16copyFolder('src', 'dist');17import {copyFolder} from 'ts-auto-mock';18copyFolder('src', 'dist');19import {copyFolder} from 'ts-auto-mock';20copyFolder('src', 'dist');

Full Screen

Using AI Code Generation

copy

Full Screen

1const copyFolder = require('ts-auto-mock/copyFolder').copyFolder;2copyFolder({3 callback: () => {4 console.log('done!');5 }6});7{8 "scripts": {9 },10}11module.exports = {12};13const tsAutoMock = require('ts-auto-mock');14tsAutoMock.setOptions({15 callback: () => {16 console.log('done!');17 }18});19tsAutoMock.enable();

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run ts-auto-mock automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful