'use strict';

/** Load Node.js modules. */
var fs = require('fs'),
    path = require('path');

/** Load other modules. */
var _ = require('lodash/lodash.js');

/** Used to indicate if running in Windows. */
var isWindows = process.platform == 'win32';

/*----------------------------------------------------------------------------*/

/**
 * The path separator.
 *
 * @memberOf util.path
 * @type string
 */
var sep = path.sep || (isWindows ? '\\' : '/');

/**
 * The escaped path separator used for inclusion in RegExp strings.
 *
 * @memberOf util.path
 * @type string
 */
var sepEscaped = _.escapeRegExp(sep);

/** Used to determine if a path is prefixed with a drive letter or dot-slash. */
var rePrefixed = RegExp('^(?:' + (isWindows ? '[a-zA-Z]:|' : '') + '\\.?)' + sepEscaped);

/*----------------------------------------------------------------------------*/

/**
 * Creates a deep clone of `value` with function properties copied by reference.
 *
 * @private
 * @param {*} value The value to deep clone.
 * @returns {*} Returns the deep cloned value.
 */
var cloneDeep = _.partial(_.cloneDeep, _, function(value) {
  return _.isFunction(value) ? value : undefined;
});

/*----------------------------------------------------------------------------*/

/**
 * Makes the given `dirname` directory, without throwing errors for existing
 * directories and making parent directories as needed.
 *
 * @memberOf util.fs
 * @param {string} dirname The path of the directory.
 * @param {number|string} [mode='0777'] The permission mode.
 */
function mkdirpSync(dirname, mode) {
  dirname = path.normalize(dirname);

  // Ensure relative paths are prefixed with `./`.
  if (!rePrefixed.test(dirname)) {
    dirname = '.' + sep + dirname;
  }
  dirname.split(sep).reduce(function(currPath, segment) {
    currPath += sep + segment;
    try {
      currPath = fs.realpathSync(currPath);
    } catch(e) {
      fs.mkdirSync(currPath, mode);
    }
    return currPath;
  });
}

/**
 * Removes files or directories and their contents recursively.
 *
 * @memberOf util.fs
 * @param {string} pathname The path of the file or directory.
 */
function rmrfSync(pathname) {
  pathname = path.normalize(pathname);

  // Safety first! Limit to modifying lodash-cli.
  if (!_.startsWith(pathname, path.dirname(__dirname) + sep)) {
    return;
  }
  try {
    pathname = fs.realpathSync(pathname);
  } catch(e) {
    return;
  }
  if (!fs.statSync(pathname).isDirectory()) {
    fs.unlinkSync(pathname);
    return;
  }
  fs.readdirSync(pathname).forEach(function(identifier) {
    var currPath = path.join(pathname, identifier);
    if (fs.statSync(currPath).isDirectory()) {
      rmrfSync(currPath);
    } else {
      fs.unlinkSync(currPath);
    }
  });
  fs.rmdirSync(pathname);
}

/*----------------------------------------------------------------------------*/

/**
 * The utility object.
 *
 * @type Object
 */
var util = {

  /**
   * The file system object.
   *
   * @memberOf util
   * @type Object
   */
  'fs': _.defaults(cloneDeep(fs), {
    'existsSync': fs.existsSync || path.existsSync,
    'mkdirpSync': mkdirpSync,
    'rmrfSync': rmrfSync
  }),

  /**
   * The path object.
   *
   * @memberOf util
   * @type Object
   */
  'path': _.defaults(cloneDeep(path), {
    'sep': sep
  })
};

/*----------------------------------------------------------------------------*/

module.exports = util;

@@ -3278,16 +3278,46 @@
 ep': sep
+,%0A    'sepEscaped': sepEscaped
 %0A  %7D)%0A%7D;

Fix test fails by adding back `util.sepEscaped`.