After failing to load a project, this function determines which project path to fallback to.
@return {$.Promise} Promise that resolves to a project path {string}
960208
function _getFallbackProjectPath() {
        var fallbackPaths = [],
            recentProjects = PreferencesManager.getViewState("recentProjects") || [],
            deferred = new $.Deferred();

        // Build ordered fallback path array
        if (recentProjects.length > 1) {
            // *Most* recent project is the one that just failed to load, so use second most recent
            fallbackPaths.push(recentProjects[1]);
        }

        // Next is Getting Started project
        fallbackPaths.push(_getWelcomeProjectPath());

        // Helper func for Async.firstSequentially()
        function processItem(path) {
            var deferred = new $.Deferred(),
                fileEntry = FileSystem.getDirectoryForPath(path);

            fileEntry.exists(function (err, exists) {
                if (!err && exists) {
                    deferred.resolve();
                } else {
                    deferred.reject();
                }
            });

            return deferred.promise();
        }

        // Find first path that exists
        Async.firstSequentially(fallbackPaths, processItem)
            .done(function (fallbackPath) {
                deferred.resolve(fallbackPath);
            })
            .fail(function () {
                // Last resort is Brackets source folder which is guaranteed to exist
                deferred.resolve(FileUtils.getNativeBracketsDirectoryPath());
            });

        return deferred.promise();
    }
1113632
function(project) {
        if(project.slug.toLowerCase() === 'obs'
            || project.slug.toLowerCase() === 'bible-obs'
            || project.slug.toLowerCase() === 'bible'
            || !project.chunks_url) return Promise.resolve();


        return request.read(project.chunks_url)
            .then(function(response) {
                // consume chunk data
                if(response.status !== 200) return Promise.reject(response);

                let data;
                try {
                    data = JSON.parse(response.data);
                } catch(err) {
                    console.log(project);
                    return Promise.reject(err);
                }

                try {
                    let language_id = library.addSourceLanguage({
                        slug: 'en',
                        name: 'English',
                        direction: 'ltr'
                    });

                    // TODO: retrieve the correct versification name(s) from the source language
                    let versification_id = library.addVersification({
                        slug: 'en-US',
                        name: 'American English'
                    }, language_id);


                    if (versification_id > 0) {
                        for (let chunk of data) {
                            library.addChunkMarker({
                                chapter: padSlug(chunk.chp, 2),
                                verse: padSlug(chunk.firstvs, 2)
                            }, project.slug, versification_id);
                        }
                    }
                } catch (err) {
                    return Promise.reject(err);
                }
            });
    }
668556
function loadFromPath(path, container) {
  if (path && typeof path === 'string' && path.length > 0) {
    return load(path, container)
  }
  return Promise.resolve([])
}
159882
function (err) {
		        //if any error happened in the previous tasks, exit with a code > 0
		        if (err) {
			        var exitCode = 2;
			        console.log('[ERROR] gulp build task failed', err);
			        console.log('[FAIL] gulp build task failed - exiting with code ' + exitCode);
			        return process.exit(exitCode);
		        }
		        else {
			        return callback();
		        }
	        }
131364
function fallBack () {
      var programFilesVar = "ProgramFiles";
      if (arch === "(64)") {
        console.warn("You are using 32-bit version of Firefox on 64-bit versions of the Windows.\nSome features may not work correctly in this version. You should upgrade Firefox to the latest 64-bit version now!")
        programFilesVar = "ProgramFiles(x86)";
      }
      resolve(path.join(process.env[programFilesVar], appName, "firefox.exe"));
    }
212925
function loadNextPropertiesAsync(oBundle) {
		if ( oBundle._sNextLocale != null ) {
			return tryToLoadNextProperties(oBundle, true).then(function(oProps) {
				// if props could not be loaded, try next fallback locale
				return oProps || loadNextPropertiesAsync(oBundle);
			});
		}
		// no more fallback locales: give up
		return Promise.resolve(null);
	}
620799
function getPath(parent, unresolved) {
	let parentVisited = false;

	return Object.keys(unresolved).filter((module) => {
		if (module === parent) {
			parentVisited = true;
		}
		return parentVisited && unresolved[module];
	});
}
470579
function(){
		// If a task is currently loading this fileUrl,
		// wait for it to complete
		var loadingTask = this.context.loadingPaths[this.fileUrl];
		if (!loadingTask) return;

		var task = this;
		return loadingTask.promise.then(function() {
			task._fetchedPackage = loadingTask.getPackage();

			var firstTaskFailed = loadingTask.hadErrorLoading();
			var currentTaskIsCompatible = task.isCompatibleVersion();
			var firstTaskIsNotCompatible = !loadingTask.isCompatibleVersion();

			// Do not flag the current task as failed if:
			//
			//	- Current task fetches a version in rage and
			//	- First task had no error loading at all or
			//	- First task fetched an incompatible version
			//
			// otherwise, assume current task will fail for the same reason as
			// the first did
			if (currentTaskIsCompatible && (!firstTaskFailed || firstTaskIsNotCompatible)) {
				task.failed = false;
				task.error = null;
			}
			else if (!currentTaskIsCompatible) {
				task.failed = true;
				task.error = new Error("Incompatible package version requested");
			}
			else if (firstTaskFailed) {
				task.failed = true;
				task.error = loadingTask.error;
			}
		});
	}
1304953
function () {
		var cwd = process.cwd();
		var rootPath = cwd;
		var newRootPath = null;
		while (!fs.existsSync(path.join(process.cwd(), "node_modules/grunt"))) {
			process.chdir("..");
			newRootPath = process.cwd();
			if (newRootPath === rootPath) {
				return;
			}
			rootPath = newRootPath;
		}
		process.chdir(cwd);
		return rootPath;
	}
1184618
function getPath(path, callback) {
  fs.lstat(path, function(err, stats) {
    if(err) return callback(err);

    // Check if it's a link
    if(stats.isSymbolicLink()) fs.readlink(path, callback);

    callback(err, path);
  });
}
603371
function fetchProjects() {
	return cocoonSDK.ProjectAPI.list()
	.then((projectList) => {
		return projectList;
	})
	.catch((error) => {
		console.error("Project list couldn't be fetched.");
		console.trace(error);
		throw error;
	});
}
1297280
function() {
        return new Promise(function(resolve, reject) {
            try {
                let files;
                if(fileUtils.fileExists(resourceDir)) {
                    files = fs.readdirSync(resourceDir);
                    files = _.uniqBy(files, function (f) {
                        return path.basename(f, '.' + rc.tools.spec.file_ext);
                    }).map(function(f) { return path.join(resourceDir, f);});
                }
                if(!files) files = [];
                resolve(files);
            } catch (err) {
                reject(err);
            }
        }).then(function(files) {
            return promiseUtils.chain(rc.tools.inspect, function(err) {
                console.error(err);
                return false;
            })(files);
        });
    }
144121
function getPromise(provider, extension) {
			var contentTypeIds = provider.getProperty("contentType") || provider.getProperty("contentTypes"), //$NON-NLS-1$ //$NON-NLS-0$
			    fileTypes = provider.getProperty("fileTypes"); // backwards compatibility //$NON-NLS-0$
			if (contentTypeIds) {
				return Deferred.when(contentTypeService.isSomeExtensionOf(contentType, contentTypeIds)).then(
					function (isMatch) {
						return isMatch ? provider : null;
					});
			} else if (extension && fileTypes && fileTypes.indexOf(extension) !== -1) {
				var d = new Deferred();
				d.resolve(provider);
				return d;
			}
			return null;
		}
790246
function() {
  return Promise.resolve()
  .then(function() { return npm.loadAsync(); })
  .then(function(npm) {
    npm.config.set('spin', false);
    npm.config.set('global', true);
    npm.config.set('depth', 0);
    return Promise.promisify(npm.commands.list)([], true);
  })
  .then(function(data) { return data; });
}
211886
function(){
		// If it is already loaded check to see if it's semver compatible
		// and if so use it. Otherwise reject.
		var loadedPkg = this.context.paths[this.fileUrl];
		if(loadedPkg) {
			this._fetchedPackage = loadedPkg;
			if(!this.isCompatibleVersion()) {
				this.failed = true;
			}
			return Promise.resolve();
		}
	}
360534
function finishBasicPromise (resolve, reject) {
  return (err, res) => {
    if (err) {
      return reject(err);
    } else {
      return resolve(res);
    }
  };
}
1189302
function _checkPath (npmPath) {
  return new Promise((resolve, reject) => {
    if (npmPath) {
      fs.lstat(npmPath, (err, stats) => {
        if (err || !stats || (stats.isDirectory && !stats.isDirectory())) {
          reject(new Error(strings.givenPathNotValid(npmPath)))
        } else {
          resolve({
            path: npmPath,
            message: strings.givenPathValid(npmPath)
          })
        }
      })
    } else {
      reject(new Error('Called _checkPath() with insufficient parameters'))
    }
  })
}