Skip to content

Instantly share code, notes, and snippets.

@Noitidart
Last active August 29, 2015 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Noitidart/67a81d730ec53040189c to your computer and use it in GitHub Desktop.
Save Noitidart/67a81d730ec53040189c to your computer and use it in GitHub Desktop.
_ff-addon-snippet-OSFile_makeDir_Bug934283 - Prior to FF31 OS.File.makeDir did not recursively make directories, this function uses OS.File.makeDir but changes slightly to allow recursive directory creation.
//start - helper functions
function Deferred() {
// this function gets the Deferred object depending on what is available, if not available it throws
if (Promise && Promise.defer) {
//need import of Promise.jsm for example: Cu.import('resource:/gree/modules/Promise.jsm');
return Promise.defer();
} else if (PromiseUtils && PromiseUtils.defer) {
//need import of PromiseUtils.jsm for example: Cu.import('resource:/gree/modules/PromiseUtils.jsm');
return PromiseUtils.defer();
} else {
try {
/* A method to resolve the associated Promise with the value passed.
* If the promise is already settled it does nothing.
*
* @param {anything} value : This value is used to resolve the promise
* If the value is a Promise then the associated promise assumes the state
* of Promise passed as value.
*/
this.resolve = null;
/* A method to reject the assocaited Promise with the value passed.
* If the promise is already settled it does nothing.
*
* @param {anything} reason: The reason for the rejection of the Promise.
* Generally its an Error object. If however a Promise is passed, then the Promise
* itself will be the reason for rejection no matter the state of the Promise.
*/
this.reject = null;
/* A newly created Pomise object.
* Initially in pending state.
*/
this.promise = new Promise(function(resolve, reject) {
this.resolve = resolve;
this.reject = reject;
}.bind(this));
Object.freeze(this);
} catch (ex) {
throw new Error('Promise/Deferred is not available');
}
}
}
// end - helper functions
function makeDir_Bug934283(path, options) {
// pre FF31, using the `from` option would not work, so this fixes that so users on FF 29 and 30 can still use my addon
// the `from` option should be a string of a folder that you know exists for sure. then the dirs after that, in path will be created
// for example: path should be: `OS.Path.join('C:', 'thisDirExistsForSure', 'may exist', 'may exist2')`, and `from` should be `OS.Path.join('C:', 'thisDirExistsForSure')`
// options of like ignoreExisting is exercised on final dir
if (!('from' in options)) {
console.error('you have no need to use this, as this is meant to allow creation from a folder that you know for sure exists');
throw new Error('you have no need to use this, as this is meant to allow creation from a folder that you know for sure exists');
}
if (path.toLowerCase().indexOf(options.from.toLowerCase()) == -1) {
console.error('The `from` string was not found in `path` string');
throw new Error('The `from` string was not found in `path` string');
}
var options_from = options.from;
delete options.from;
var dirsToMake = OS.Path.split(path).components.slice(OS.Path.split(options_from).components.length);
console.log('dirsToMake:', dirsToMake);
var deferred_makeDir_Bug934283 = new Deferred();
var promise_makeDir_Bug934283 = deferred_makeDir_Bug934283.promise;
var pathExistsForCertain = options_from;
var makeDirRecurse = function() {
pathExistsForCertain = OS.Path.join(pathExistsForCertain, dirsToMake[0]);
dirsToMake.splice(0, 1);
var promise_makeDir = OS.File.makeDir(pathExistsForCertain, options);
promise_makeDir.then(
function(aVal) {
console.log('Fullfilled - promise_makeDir - ', 'ensured/just made:', pathExistsForCertain, aVal);
if (dirsToMake.length > 0) {
makeDirRecurse();
} else {
deferred_makeDir_Bug934283.resolve('this path now exists for sure: "' + pathExistsForCertain + '"');
}
},
function(aReason) {
var rejObj = {
promiseName: 'promise_makeDir',
aReason: aReason,
curPath: pathExistsForCertain
};
console.warn('Rejected - ' + rejObj.promiseName + ' - ', rejObj);
deferred_makeDir_Bug934283.reject(rejObj);
}
).catch(
function(aCaught) {
var rejObj = {name:'promise_makeDir', aCaught:aCaught};
console.error('Caught - promise_makeDir - ', rejObj);
deferred_makeDir_Bug934283.reject(rejObj); // throw aCaught;
}
);
};
makeDirRecurse();
return promise_makeDir_Bug934283;
}
// example 1
var from = OS.Path.join(OS.Constants.Path.desktopDir);
var promise_makeDirsFrom = makeDir_Bug934283(OS.Path.join(from, 'a', 'b', 'c'), {
from: from
});
promise_makeDirsFrom.then(
function(aVal) {
console.log('Fullfilled - promise_makeDirsFrom - ', aVal);
},
function(aReason) {
var rejObj = {
promiseName: 'promise_makeDirsFrom',
aReason: aReason
};
console.warn('Rejected - ' + rejObj.promiseName + ' - ', rejObj);
}
).catch(
function(aCaught) {
console.error('Caught - promise_makeDirsFrom - ', aCaught);
}
);
/* //actual no it should respect options throughout
//example 2, this shows how ignoreExisting exercises on final dir, so run this code twice you will see second one rejects with aReason.aReason.becauseExists == true
var doit = scope.makeDir_Bug934283(OS.Path.join(OS.Constants.Path.desktopDir, 'profilist_data', 'iconset', 'youtube'), {from:OS.Constants.Path.desktopDir, ignoreExisting:false});
doit.then(function(a) { console.log(a) }, function(b) { console.warn(b) }).catch(function(c){ console.error(c) });
*/
@Noitidart
Copy link
Author

README

Rev1

  • Works, creates on the desktop: ../Desktop/a/b/c/

Rev2

  • Making it not throw when caught, it properly rejects now, no more of that hanging promise crap

Rev3

  • Updated from Profilist, respects options on final dir make

Rev4

  • Updated as options should be respected throughout, the final dir make respect options should be done via tryOsFile_ifDirsNoExistMakeThenRetry

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment