docs: function mergeAndUpdateDir(sourceDirs, targetDir, options, log) {
      if (sourceDirs && typeof sourceDirs === "string") {
          sourceDirs = [ sourceDirs ];
      } else if (!Array.isArray(sourceDirs)) {
          throw new Error("A source directory path or array of paths is required.");
      }
  
      if (!targetDir || typeof targetDir !== "string") {
          throw new Error("A target directory path is required.");
      }
  
      log = log || function(message) { };
  
      var rootDir = (options && options.rootDir) || "";
  
      var include = (options && options.include) || [ "**" ];
      if (typeof include === "string") {
          include = [ include ];
      } else if (!Array.isArray(include)) {
          throw new Error("Include parameter must be a glob string or array of glob strings.");
      }
  
      var exclude = (options && options.exclude) || [];
      if (typeof exclude === "string") {
          exclude = [ exclude ];
      } else if (!Array.isArray(exclude)) {
          throw new Error("Exclude parameter must be a glob string or array of glob strings.");
      }
  
      // Scan the files in each of the source directories.
      var sourceMaps = sourceDirs.map(function (sourceDir) {
              return path.join(rootDir, sourceDir);
          }).map(function (sourcePath) {
              if (!fs.existsSync(sourcePath)) {
                  throw new Error("Source directory does not exist: " + sourcePath);
              }
              return mapDirectory(rootDir, path.relative(rootDir, sourcePath), include, exclude);
          });
  
      // Scan the files in the target directory, if it exists.
      var targetMap = {};
      var targetFullPath = path.join(rootDir, targetDir);
      if (fs.existsSync(targetFullPath)) {
          targetMap = mapDirectory(rootDir, targetDir, include, exclude);
      }
  
      var pathMap = mergePathMaps(sourceMaps, targetMap, targetDir);
  
      var updated = false;
  
      // Iterate in sorted order to ensure directories are created before files under them.
      Object.keys(pathMap).sort().forEach(function (subPath) {
          var entry = pathMap[subPath];
          updated = updatePathWithStats(
              entry.sourcePath,
              entry.sourceStats,
              entry.targetPath,
              entry.targetStats,
              options,
              log) || updated;
      });
  
      return updated;
  }