Override extraFileActions to check for package documentation
504074
@Override
    protected void extraFileActions(PackageSymbol pack, JavaFileObject fo) {
        if (fo.isNameCompatible("package", JavaFileObject.Kind.HTML))
            docenv.getPackageDoc(pack).setDocPath(fo);
    }
1230428
private void checkAndLoadDependentExtensions() {
        boolean changed = false;
        for (Entry<String, AddOnClassLoader> entry : new HashMap<>(addOnLoaders).entrySet()) {
            AddOn runningAddOn = aoc.getAddOn(entry.getKey());
            if (runningAddOn.getInstallationStatus() == AddOn.InstallationStatus.UNINSTALLATION_FAILED) {
                continue;
            }
            for (String extClassName : runningAddOn.getExtensionsWithDeps()) {
                if (!runningAddOn.isExtensionLoaded(extClassName)) {
                    AddOn.AddOnRunRequirements reqs = runningAddOn.calculateExtensionRunRequirements(
                            extClassName,
                            aoc.getInstalledAddOns());
                    ExtensionRunRequirements extReqs = reqs.getExtensionRequirements().get(0);
                    if (extReqs.isRunnable()) {
                        List<AddOnClassLoader> dependencies = new ArrayList<>(extReqs.getDependencies().size());
                        for (AddOn addOnDep : extReqs.getDependencies()) {
                            dependencies.add(addOnLoaders.get(addOnDep.getId()));
                        }
                        AddOnClassLoader extAddOnClassLoader = new AddOnClassLoader(
                                entry.getValue(),
                                dependencies,
                                runningAddOn.getExtensionAddOnClassnames(extClassName));
                        Extension ext = loadAddOnExtension(runningAddOn, extReqs.getClassname(), extAddOnClassLoader);
                        AddOnInstaller.installAddOnExtension(runningAddOn, ext);
                        runnableAddOns.get(runningAddOn).add(extReqs.getClassname());
                        changed = true;
                    }
                }
            }
        }

        if (changed) {
            saveAddOnsRunState(runnableAddOns);
        }
    }
92523
def clean():
    ""
    src_dir = easy.options.setdefault("docs", {}).get('src_dir', None)
    if src_dir is None:
        src_dir = 'src' if easy.path('src').exists() else '.'

    with easy.pushd(src_dir):
        for pkg in set(easy.options.setup.packages) | set(("tests",)):
            for filename in glob.glob(pkg.replace('.', os.sep) + "/*.py[oc~]"):
                easy.path(filename).remove()
1146582
def documentation(self, add_to=None):
        """"""
        doc = OrderedDict if add_to is None else add_to

        usage = self.interface.spec.__doc__
        if usage:
            doc['usage'] = usage
        if getattr(self, 'requires', None):
            doc['requires'] = [getattr(requirement, '__doc__', requirement.__name__) for requirement in self.requires]
        doc['outputs'] = OrderedDict()
        doc['outputs']['format'] = self.outputs.__doc__
        doc['outputs']['content_type'] = self.outputs.content_type
        parameters = [param for param in self.parameters if not param in ('request', 'response', 'self')
                                                        and not param in ('api_version', 'body')
                                                        and not param.startswith('hug_')
                                                        and not hasattr(param, 'directive')]
        if parameters:
            inputs = doc.setdefault('inputs', OrderedDict())
            types = self.interface.spec.__annotations__
            for argument in parameters:
                kind = types.get(argument, text)
                if getattr(kind, 'directive', None) is True:
                    continue

                input_definition = inputs.setdefault(argument, OrderedDict())
                input_definition['type'] = kind if isinstance(kind, str) else kind.__doc__
                default = self.defaults.get(argument, None)
                if default is not None:
                    input_definition['default'] = default

        return doc
242356
def find_files_to_add(self, exclude_build=True):  # type: (bool) -> list
        
        to_add = []

        for include in self._module.includes:
            for file in include.elements:
                if "__pycache__" in str(file):
                    continue

                if file.is_dir():
                    continue

                file = file.relative_to(self._path)

                if self.is_excluded(file) and isinstance(include, PackageInclude):
                    continue

                if file.suffix == ".pyc":
                    continue

                if file in to_add:
                    # Skip duplicates
                    continue

                self._io.writeln(
                    " - Adding: <comment>{}</comment>".format(str(file)),
                    verbosity=self._io.VERBOSITY_VERY_VERBOSE,
                )
                to_add.append(file)

        # Include project files
        self._io.writeln(
            " - Adding: <comment>pyproject.toml</comment>",
            verbosity=self._io.VERBOSITY_VERY_VERBOSE,
        )
        to_add.append(Path("pyproject.toml"))

        # If a license file exists, add it
        for license_file in self._path.glob("LICENSE*"):
            self._io.writeln(
                " - Adding: <comment>{}</comment>".format(
                    license_file.relative_to(self._path)
                ),
                verbosity=self._io.VERBOSITY_VERY_VERBOSE,
            )
            to_add.append(license_file.relative_to(self._path))

        # If a README is specificed we need to include it
        # to avoid errors
        if "readme" in self._poetry.local_config:
            readme = self._path / self._poetry.local_config["readme"]
            if readme.exists():
                self._io.writeln(
                    " - Adding: <comment>{}</comment>".format(
                        readme.relative_to(self._path)
                    ),
                    verbosity=self._io.VERBOSITY_VERY_VERBOSE,
                )
                to_add.append(readme.relative_to(self._path))

        # If a build script is specified and explicitely required
        # we add it to the list of files
        if self._package.build and not exclude_build:
            to_add.append(Path(self._package.build))

        return sorted(to_add)
354677
function ignore(dir, options) {
  var jpmignore = path.join(dir, ".jpmignore");
  var defaultRules = ["*.zip", ".*", "test/", ".jpmignore", "*.xpi"];

  return utils.getManifest({addonDir: options.addonDir})
    .then(function(manifest) {
      return fs.exists(jpmignore);
    })
    .then(function(exists) {
      if (exists) {
        if (options.verbose) {
          console.log(".jpmignore found");
        }
        return fs.stat(jpmignore)
          .then(function(stat) {
            if (stat.isFile()) {
              return fs.readFile(jpmignore)
                .then(function(data) {
                  return data.toString().replace(/[\r\n]/, "\n").split("\n");
                });
            } else {
              console.warn(
                ".jpmignore is not a file, fallback to use " +
                  "default filter rules");
              return defaultRules;
            }
          });
      } else {
        if (options.verbose) {
          console.warn(
            ".jpmignore does not exist, fallback to use default filter rules");
        }
        return defaultRules;
      }
    })
    .then(function(lines) {
      // Add "manifest.json" to always exclude it from the xpi (See
      // https://github.com/mozilla-jetpack/jpm/pull/566 for rationale),
      // but ensure the "webextension/manifest.json", that is used for the
      // webextension embedded in an SDK hybrid add-on, is always included
      // (See https://github.com/mozilla-jetpack/jpm/pull/578 for rationale).
      lines = ["manifest.json", "!webextension/manifest.json"].concat(lines);

      var rules = lines.filter(function(e) {
        // exclude blank lines and comments
        return !/^\s*(#|$)/.test(e);
      });
      // http://git-scm.com/docs/gitignore
      // the last matching pattern decides the outcome
      // reverse rules and break at first matched rule when filtering
      return rules.reverse().map(function(rule) {
        return new Minimatch(rule, {
          matchBase: true,
          dot: true,
          flipNegate: true
        });
      });
    })
    .then(function(rules) {
      return listdir(dir, rules, dir, true);
    });
}
928308
async function getAdditionalFiles(config, packageFiles) {
  logger.trace({ config }, 'getAdditionalFiles');
  const artifactErrors = [];
  const updatedArtifacts = [];
  if (!(packageFiles.npm && packageFiles.npm.length)) {
    return { artifactErrors, updatedArtifacts };
  }
  if (!config.updateLockFiles) {
    logger.info('Skipping lock file generation');
    return { artifactErrors, updatedArtifacts };
  }
  logger.debug('Getting updated lock files');
  if (
    config.updateType === 'lockFileMaintenance' &&
    config.parentBranch &&
    (await platform.branchExists(config.branchName))
  ) {
    logger.debug('Skipping lockFileMaintenance update');
    return { artifactErrors, updatedArtifacts };
  }
  const dirs = module.exports.determineLockFileDirs(config, packageFiles);
  logger.debug({ dirs }, 'lock file dirs');
  await module.exports.writeExistingFiles(config, packageFiles);
  await module.exports.writeUpdatedPackageFiles(config, packageFiles);

  process.env.NPM_CONFIG_CACHE =
    process.env.NPM_CONFIG_CACHE || upath.join(config.cacheDir, './others/npm');
  await fs.ensureDir(process.env.NPM_CONFIG_CACHE);
  process.env.YARN_CACHE_FOLDER =
    process.env.YARN_CACHE_FOLDER ||
    upath.join(config.cacheDir, './others/yarn');
  await fs.ensureDir(process.env.YARN_CACHE_FOLDER);
  process.env.npm_config_store =
    process.env.npm_config_store ||
    upath.join(config.cacheDir, './others/pnpm');
  await fs.ensureDir(process.env.npm_config_store);

  const env =
    global.trustLevel === 'high'
      ? process.env
      : {
          HOME: process.env.HOME,
          PATH: process.env.PATH,
          NPM_CONFIG_CACHE: process.env.NPM_CONFIG_CACHE,
          YARN_CACHE_FOLDER: process.env.YARN_CACHE_FOLDER,
          npm_config_store: process.env.npm_config_store,
        };
  env.NODE_ENV = 'dev';

  let token = '';
  try {
    ({ token } = hostRules.find({ platform: config.platform }));
    token += '@';
  } catch (err) {
    logger.warn({ err }, 'Error getting token for packageFile');
  }
  for (const lockFile of dirs.npmLockDirs) {
    const lockFileDir = path.dirname(lockFile);
    const fileName = path.basename(lockFile);
    logger.debug(`Generating ${fileName} for ${lockFileDir}`);
    const upgrades = config.upgrades.filter(
      upgrade => upgrade.npmLock === lockFile
    );
    const res = await npm.generateLockFile(
      upath.join(config.localDir, lockFileDir),
      env,
      fileName,
      config,
      upgrades
    );
    if (res.error) {
      // istanbul ignore if
      if (res.stderr && res.stderr.includes('No matching version found for')) {
        for (const upgrade of config.upgrades) {
          if (
            res.stderr.includes(
              `No matching version found for ${upgrade.depName}`
            )
          ) {
            logger.info(
              { dependency: upgrade.depName, type: 'npm' },
              'lock file failed for the dependency being updated - skipping branch creation'
            );
            throw new Error('registry-failure');
          }
        }
      }
      artifactErrors.push({
        lockFile,
        stderr: res.stderr,
      });
    } else {
      const existingContent = await platform.getFile(
        lockFile,
        config.parentBranch
      );
      if (res.lockFile !== existingContent) {
        logger.debug(`${lockFile} needs updating`);
        updatedArtifacts.push({
          name: lockFile,
          contents: res.lockFile.replace(new RegExp(`${token}`, 'g'), ''),
        });
      } else {
        logger.debug(`${lockFile} hasn't changed`);
      }
    }
  }

  for (const lockFile of dirs.yarnLockDirs) {
    const lockFileDir = path.dirname(lockFile);
    logger.debug(`Generating yarn.lock for ${lockFileDir}`);
    const lockFileName = upath.join(lockFileDir, 'yarn.lock');
    const upgrades = config.upgrades.filter(
      upgrade => upgrade.yarnLock === lockFile
    );
    const res = await yarn.generateLockFile(
      upath.join(config.localDir, lockFileDir),
      env,
      config,
      upgrades
    );
    if (res.error) {
      // istanbul ignore if
      if (res.stderr && res.stderr.includes(`Couldn't find any versions for`)) {
        for (const upgrade of config.upgrades) {
          /* eslint-disable no-useless-escape */
          if (
            res.stderr.includes(
              `Couldn't find any versions for \\\"${upgrade.depName}\\\"`
            )
          ) {
            logger.info(
              { dependency: upgrade.depName, type: 'yarn' },
              'lock file failed for the dependency being updated - skipping branch creation'
            );
            throw new Error('registry-failure');
          }
          /* eslint-enable no-useless-escape */
        }
      }
      artifactErrors.push({
        lockFile,
        stderr: res.stderr,
      });
    } else {
      const existingContent = await platform.getFile(
        lockFileName,
        config.parentBranch
      );
      if (res.lockFile !== existingContent) {
        logger.debug('yarn.lock needs updating');
        updatedArtifacts.push({
          name: lockFileName,
          contents: res.lockFile,
        });
      } else {
        logger.debug("yarn.lock hasn't changed");
      }
    }
  }

  for (const lockFile of dirs.pnpmShrinkwrapDirs) {
    const lockFileDir = path.dirname(lockFile);
    logger.debug(`Generating pnpm-lock.yaml for ${lockFileDir}`);
    const res = await pnpm.generateLockFile(
      upath.join(config.localDir, lockFileDir),
      env,
      config.binarySource
    );
    if (res.error) {
      // istanbul ignore if
      if (res.stdout && res.stdout.includes(`No compatible version found:`)) {
        for (const upgrade of config.upgrades) {
          if (
            res.stdout.includes(
              `No compatible version found: ${upgrade.depName}`
            )
          ) {
            logger.info(
              { dependency: upgrade.depName, type: 'pnpm' },
              'lock file failed for the dependency being updated - skipping branch creation'
            );
            throw new Error('registry-failure');
          }
        }
      }
      artifactErrors.push({
        lockFile,
        stderr: res.stderr,
      });
    } else {
      const existingContent = await platform.getFile(
        lockFile,
        config.parentBranch
      );
      if (res.lockFile !== existingContent) {
        logger.debug('pnpm-lock.yaml needs updating');
        updatedArtifacts.push({
          name: lockFile,
          contents: res.lockFile,
        });
      } else {
        logger.debug("pnpm-lock.yaml hasn't changed");
      }
    }
  }

  for (const lernaDir of dirs.lernaDirs) {
    let lockFile;
    logger.debug(`Finding package.json for lerna directory "${lernaDir}"`);
    const lernaPackageFile = packageFiles.npm.find(
      p => path.dirname(p.packageFile) === lernaDir
    );
    if (!lernaPackageFile) {
      logger.debug('No matching package.json found');
      throw new Error('lerna-no-lockfile');
    }
    if (lernaPackageFile.lernaClient === 'npm') {
      lockFile = config.npmLock || 'package-lock.json';
    } else {
      lockFile = config.yarnLock || 'yarn.lock';
    }
    const skipInstalls =
      lockFile === 'npm-shrinkwrap.json' ? false : config.skipInstalls;
    const res = await lerna.generateLockFiles(
      lernaPackageFile.lernaClient,
      upath.join(config.localDir, lernaDir),
      env,
      skipInstalls,
      config.binarySource
    );
    // istanbul ignore else
    if (res.error) {
      // istanbul ignore if
      if (
        res.stderr &&
        res.stderr.includes('ENOSPC: no space left on device')
      ) {
        throw new Error('disk-space');
      }
      for (const upgrade of config.upgrades) {
        /* eslint-disable no-useless-escape */
        if (
          res.stderr.includes(
            `Couldn't find any versions for \\\"${upgrade.depName}\\\"`
          )
        ) {
          logger.info(
            { dependency: upgrade.depName, type: 'yarn' },
            'lock file failed for the dependency being updated - skipping branch creation'
          );
          throw new Error('registry-failure');
        }
        /* eslint-enable no-useless-escape */
        if (
          res.stderr.includes(
            `No matching version found for ${upgrade.depName}`
          )
        ) {
          logger.info(
            { dependency: upgrade.depName, type: 'npm' },
            'lock file failed for the dependency being updated - skipping branch creation'
          );
          throw new Error('registry-failure');
        }
      }
      artifactErrors.push({
        lockFile,
        stderr: res.stderr,
      });
    } else {
      for (const packageFile of packageFiles.npm) {
        const filename = packageFile.npmLock || packageFile.yarnLock;
        logger.trace('Checking for ' + filename);
        const existingContent = await platform.getFile(
          filename,
          config.parentBranch
        );
        if (existingContent) {
          logger.trace('Found lock file');
          const lockFilePath = upath.join(config.localDir, filename);
          logger.trace('Checking against ' + lockFilePath);
          try {
            let newContent;
            try {
              newContent = await fs.readFile(lockFilePath, 'utf8');
            } catch (err) {
              newContent = await fs.readFile(
                lockFilePath.replace('npm-shrinkwrap.json', 'package-lock.json')
              );
            }
            if (newContent !== existingContent) {
              logger.debug('File is updated: ' + lockFilePath);
              updatedArtifacts.push({
                name: filename,
                contents: newContent,
              });
            } else {
              logger.trace('File is unchanged');
            }
          } catch (err) {
            if (config.updateType === 'lockFileMaintenance') {
              logger.info(
                { packageFile, lockFilePath },
                'No lock file found after lerna lockFileMaintenance'
              );
            } else {
              logger.warn(
                { packageFile, lockFilePath },
                'No lock file found after lerna bootstrap'
              );
            }
          }
        } else {
          logger.trace('No lock file found');
        }
      }
    }
  }

  return { artifactErrors, updatedArtifacts };
}
1362275
def matching(self):
        
        for sbo in self.package_not_found:
            for pkg in self.data:
                if sbo in pkg and pkg not in self.blacklist:
                    self.package_found.append(pkg)
641361
def strip_sdist_extras(filelist):
    
    return [name for name in filelist
            if not file_matches(name, IGNORE)
            and not file_matches_regexps(name, IGNORE_REGEXPS)]
800644
function getPackageExportNames(packagePath) {
  const packageMeta = getPackageMeta(packagePath);
  const packageModulePath = path.join(packagePath, packageMeta.module);
  const moduleFileSource = fs.readFileSync(packageModulePath, "utf8");
  const { body } = esprima.parseModule(moduleFileSource);

  return body.reduce((result, statement) => {
    if (statement.type === "ExportDefaultDeclaration") {
      return result.concat(["default"]);
    }

    if (statement.type === "ExportNamedDeclaration") {
      return result.concat(getNamesFromDeclaration(statement));
    }

    return result;
  }, []);
}
420228
def requires(self, extras=()):
        """"""
        dm = self._dep_map
        deps = []
        deps.extend(dm.get(None, ()))
        for ext in extras:
            try:
                deps.extend(dm[safe_extra(ext)])
            except KeyError:
                raise UnknownExtra(
                    "%s has no such extra feature %r" % (self, ext)
                )
        return deps
734797
def get_extra_commands():
    """"""
    from ambry.run import find_config_file
    from ambry.dbexceptions import ConfigurationError
    from ambry.util import yaml

    try:
        plugins_dir = find_config_file('cli.yaml')
    except ConfigurationError:
        return []

    with open(plugins_dir) as f:
        cli_modules = yaml.load(f)

    return cli_modules
105853
def find_packages(where='.', exclude=(), invalidate_cache=False):
    

    if exclude:
        warnings.warn(
            "Use of the exclude parameter is no longer supported since it does "
            "not work as expected. Use add_exclude_packages instead. Note that "
            "it must be called prior to any other calls from setup helpers.",
            AstropyDeprecationWarning)

    # Calling add_exclude_packages after this point will have no effect
    _module_state['excludes_too_late'] = True

    if not invalidate_cache and _module_state['package_cache'] is not None:
        return _module_state['package_cache']

    packages = _find_packages(
        where=where, exclude=list(_module_state['exclude_packages']))
    _module_state['package_cache'] = packages

    return packages
127803
def maybe_2to3(filename, modname=None):
    """"""
    need_2to3 = False
    filename = os.path.abspath(filename)
    if any(filename.startswith(d) for d in DIRS):
        need_2to3 = True
    elif modname is not None and any(modname.startswith(p) for p in PACKAGES):
        need_2to3 = True
    if not need_2to3:
        return filename
    outfilename = '/_auto2to3_'.join(os.path.split(filename))
    if (not os.path.exists(outfilename) or
        os.stat(filename).st_mtime > os.stat(outfilename).st_mtime):
        try:
            with open(filename) as file:
                contents = file.read()
            contents = rt.refactor_docstring(contents, filename)
            tree = rt.refactor_string(contents, filename)
        except Exception as err:
            raise ImportError("2to3 couldn't convert %r" % filename)
        outfile = open(outfilename, 'wb')
        outfile.write(str(tree).encode('utf8'))
        outfile.close()
    return outfilename
1116076
def compile_type_document(self, imports_block, package, name, declaration):
        

        outer_type = name.rpartition('.')[0]

        document = util.Document()
        document.add(imports_block)
        document.add_heading(name, '=')

        method_summary = util.StringBuilder()
        document.add_object(method_summary)

        package_dir = util.Directive('java:package', package)
        package_dir.add_option('noindex')
        document.add_object(package_dir)

        # Add type-level documentation
        type_dir = self.compile_type(declaration)
        if outer_type:
            type_dir.add_option('outertype', outer_type)
        document.add_object(type_dir)

        if isinstance(declaration, javalang.tree.EnumDeclaration):
            enum_constants = list(declaration.body.constants)
            enum_constants.sort(key=lambda c: c.name)

            document.add_heading('Enum Constants')
            for enum_constant in enum_constants:
                if self.member_headers:
                    document.add_heading(enum_constant.name, '^')
                c = self.compile_enum_constant(name, enum_constant)
                c.add_option('outertype', name)
                document.add_object(c)

        fields = list(filter(self.filter, declaration.fields))
        if fields:
            document.add_heading('Fields', '-')
            fields.sort(key=lambda f: f.declarators[0].name)
            for field in fields:
                if self.member_headers:
                    document.add_heading(field.declarators[0].name, '^')
                f = self.compile_field(field)
                f.add_option('outertype', name)
                document.add_object(f)

        constructors = list(filter(self.filter, declaration.constructors))
        if constructors:
            document.add_heading('Constructors', '-')
            constructors.sort(key=lambda c: c.name)
            for constructor in constructors:
                if self.member_headers:
                    document.add_heading(constructor.name, '^')
                c = self.compile_constructor(constructor)
                c.add_option('outertype', name)
                document.add_object(c)

        methods = list(filter(self.filter, declaration.methods))
        if methods:
            document.add_heading('Methods', '-')
            methods.sort(key=lambda m: m.name)
            for method in methods:
                if self.member_headers:
                    document.add_heading(method.name, '^')
                m = self.compile_method(method)
                m.add_option('outertype', name)
                document.add_object(m)

        return document
1352775
def DocFileSuite(*paths, **kwargs):
    """"""
    kwargs.setdefault('setUp', setUpBrowser)
    kwargs.setdefault('tearDown', tearDownBrowser)
    kwargs.setdefault('globs', {}).update(Browser=Browser)
    kwargs.setdefault('optionflags', doctest.NORMALIZE_WHITESPACE |
                                     doctest.REPORT_ONLY_FIRST_FAILURE |
                                     doctest.ELLIPSIS)
    if 'package' not in kwargs:
        # Resolve relative names based on the caller's module
        kwargs['package'] = doctest._normalize_module(None)
        kwargs['module_relative'] = True
    return doctest.DocFileSuite(*paths, **kwargs)
881760
function enableModuleReplacement(opts) {
  // TODO: use proxy here instead of just monkey-patching so all furure extensions are tracked automatically
  const savedExtensions = Module._extensions;
  const _extensions = {};
  Object.keys(savedExtensions).forEach(extension => {
    _extensions[extension] = function(module, filename) {
      addHMRHooks(module);
      savedExtensions[extension](module, filename);
    };
  });

  Module._extensions = _extensions;

  // module is changed, which dependency needs to be reloaded?
  function collectDependencies(module) {
    let paths = [];
    function pathsToAcceptingModules(path, root) {
      const requiredMe = parents[root.filename];
      if (module.hot._selfAccepted) {
        paths.push(path.concat(root.filename));
        return;
      }
      if (module.hot._selfDeclined) {
        return;
      }
      for (let next in requiredMe) {
        let parentHotRuntime = requiredMe[next].hot;
        if (parentHotRuntime._acceptedDependencies[root.filename]) {
          paths.push(path.concat(root.filename));
          continue;
        }
        if (parentHotRuntime._declinedDependencies[root.filename]) {
          continue;
        }
        pathsToAcceptingModules(path.concat(root.filename), requiredMe[next]);
      }
    }
    pathsToAcceptingModules([], module);
    return paths;
  }

  opts = opts || {};
  function ignore(path) {
    if (isBuiltinModule(path)) {
      return true;
    }
    if (typeof opts.ignore === 'function') {
      return opts.ignore(path);
    }
    if (opts.ignore instanceof RegExp) {
      return !!opts.ignore.exec(path);
    }
  }

  const watching = {};
  function startWatching(path) {
    if (ignore(path)) {
      return;
    }
    if (watching[path]) {
      return;
    }
    watching[path] = watch(path, { persistent: false }, function(eventType, filename) {
      const oldModule = require.cache[path];

      const deps = oldModule ? collectDependencies(oldModule) : [];
      const reloaded = {};

      for (let d = 0; d < deps.length; ++d) {
        for (let l = 0; l < deps[d].length; ++l) {
          const path = deps[d][l];
          if (reloaded[path]) {
            continue;
          }
          reloaded[path] = true;
          const oldModule = require.cache[path];
          if (oldModule.hot._disposeHandlers) {
            oldModule.hot._disposeHandlers.forEach(h => h());
          }
          const newModule = new Module(path, oldModule.parent);
          addHMRHooks(newModule);
          try {
            newModule.load(path);
            require.cache[path] = newModule;
            const ps = parents[path];
            for (parentPath in ps) {
              let parent = require.cache[parentPath];
              if (parent.hot._acceptedDependencies[path]) {
                // TODO: try/catch here?
                parent.hot._acceptedDependencies[path](path);
              }
            }
          } catch (e) {
            console.log(e);
          }
        }
      }
    });
  }

  // monkey-patch require
  const originalRequire = Module.prototype.require;
  const originalLoad = Module._load;
  const originalCompile = Module.prototype._compile;

  const parents = {};
  Module._load = function(request, parent, isMain) {
    const requirePath = Module._resolveFilename(request, parent);
    if (ignore(requirePath)) {
      return originalLoad(request, parent, isMain);
    }

    startWatching(requirePath);
    const parentPath = parent && parent.filename;
    const myParents = parents[requirePath];
    if (parentPath) {
      if (!myParents) {
        var p = {};
        p[parentPath] = parent;
        parents[requirePath] = p;
      } else {
        myParents[parentPath] = parent;
      }
    }
    return originalLoad(request, parent, isMain);
  };

  if (module.parent) {
    if (!module.parent.hot) {
      addHMRHooks(module.parent);
    }
  }

  function addHMRHooks(module) {
    const resolve = name => {
      return Module._resolveFilename(name, module);
    };
    // copied directly from webpack HMR
    // https://github.com/webpack/webpack/blob/0257f6c6e41255cf26230c099fb90140f1f0e0bb/lib/HotModuleReplacement.runtime.js#L77
    var hot = {
      // private stuff
      _acceptedDependencies: {},
      _declinedDependencies: {},
      _selfAccepted: false,
      _selfDeclined: false,
      _disposeHandlers: [],
      // _main: hotCurrentChildModule !== moduleId,

      // Module API
      active: true,
      accept: function(dep, callback) {
        if (typeof dep === 'undefined') hot._selfAccepted = true;
        else if (typeof dep === 'function') hot._selfAccepted = dep;
        else if (typeof dep === 'object')
          for (var i = 0; i < dep.length; i++)
            hot._acceptedDependencies[resolve(dep[i])] = callback || function() {};
        else hot._acceptedDependencies[resolve(dep)] = callback || function() {};
      },
      decline: function(dep) {
        if (typeof dep === 'undefined') hot._selfDeclined = true;
        else if (typeof dep === 'object')
          for (var i = 0; i < dep.length; i++) hot._declinedDependencies[resolve(dep[i])] = true;
        else hot._declinedDependencies[resolve(dep)] = true;
      },
      dispose: function(callback) {
        hot._disposeHandlers.push(callback);
      },
      addDisposeHandler: function(callback) {
        hot._disposeHandlers.push(callback);
      },
      removeDisposeHandler: function(callback) {
        var idx = hot._disposeHandlers.indexOf(callback);
        if (idx >= 0) hot._disposeHandlers.splice(idx, 1);
      }
      /*
      // TODO: Management API
      check: hotCheck,
      apply: hotApply,

      status: function(l) {
        if (!l) return hotStatus;
        hotStatusHandlers.push(l);
      },
      addStatusHandler: function(l) {
        hotStatusHandlers.push(l);
      },
      removeStatusHandler: function(l) {
        var idx = hotStatusHandlers.indexOf(l);
        if (idx >= 0) hotStatusHandlers.splice(idx, 1);
      }

      //inherit from previous dispose call
      data: hotCurrentModuleData[moduleId]
    */
    };
    module.hot = hot;
  }
}