function copyDirectoryEntry(source, destination, options) {
        options = options || {};
        options.infos = options.infos || {};

        var parseOffsets    = options.parseOffsets || false,
            removePrefix    = options.removePrefix || true,
            deferred        = new $.Deferred(),
            destDir         = _getFileSystem().getDirectoryForPath(destination);

        // create the destination folder
        destDir.create(function (err) {
            if (err && err !== FileSystemError.ALREADY_EXISTS) {
                deferred.reject();
                return;
            }

            source.getContents(function (err, contents) {
                if (!err) {
                    // copy all children of this directory
                    var copyChildrenPromise = Async.doInParallel(
                        contents,
                        function copyChild(child) {
                            var childDestination = destination + "/" + child.name,
                                promise;

                            if (child.isDirectory) {
                                promise = copyDirectoryEntry(child, childDestination, options);
                            } else {
                                promise = copyFileEntry(child, childDestination, options);

                                if (parseOffsets) {
                                    // save offset data for each file path
                                    promise.done(function (destinationEntry, offsets, text) {
                                        options.infos[childDestination] = {
                                            offsets     : offsets,
                                            fileEntry   : destinationEntry,
                                            text        : text
                                        };
                                    });
                                }
                            }

                            return promise;
                        }
                    );

                    copyChildrenPromise.then(deferred.resolve, deferred.reject);
                } else {
                    deferred.reject(err);
                }
            });
        });

        deferred.always(function () {
            // remove destination path prefix
            if (removePrefix && options.infos) {
                var shortKey;
                Object.keys(options.infos).forEach(function (key) {
                    shortKey = key.substr(destination.length + 1);
                    options.infos[shortKey] = options.infos[key];
                });
            }
        });

        return deferred.promise();
    }
Copy a directory source to a destination
@param {!Directory} source Directory to copy
@param {!string} destination Destination path to copy the source directory to
@param {?{parseOffsets:boolean, infos:Object, removePrefix:boolean}}} options
    parseOffsets - allows optional offset markup parsing. File is written to the
      destination path without offsets. Offset data is passed to the
      doneCallbacks of the promise.
    infos - an optional Object used when parseOffsets is true. Offset
      information is attached here, indexed by the file destination path.
    removePrefix - When parseOffsets is true, set removePrefix true
      to add a new key to the infos array that drops the destination
      path root.
@return {$.Promise} A promise resolved when the directory and all it's
    contents are copied to the destination or rejected immediately
    upon the first error.