You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

64 lines
1.6 KiB

4 years ago
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const getPaths = require("./getPaths");
  7. const forEachBail = require("./forEachBail");
  8. module.exports = class SymlinkPlugin {
  9. constructor(source, target) {
  10. this.source = source;
  11. this.target = target;
  12. }
  13. apply(resolver) {
  14. const target = resolver.ensureHook(this.target);
  15. const fs = resolver.fileSystem;
  16. resolver
  17. .getHook(this.source)
  18. .tapAsync("SymlinkPlugin", (request, resolveContext, callback) => {
  19. const pathsResult = getPaths(request.path);
  20. const pathSeqments = pathsResult.seqments;
  21. const paths = pathsResult.paths;
  22. let containsSymlink = false;
  23. forEachBail.withIndex(
  24. paths,
  25. (path, idx, callback) => {
  26. fs.readlink(path, (err, result) => {
  27. if (!err && result) {
  28. pathSeqments[idx] = result;
  29. containsSymlink = true;
  30. // Shortcut when absolute symlink found
  31. if (/^(\/|[a-zA-Z]:($|\\))/.test(result))
  32. return callback(null, idx);
  33. }
  34. callback();
  35. });
  36. },
  37. (err, idx) => {
  38. if (!containsSymlink) return callback();
  39. const resultSeqments =
  40. typeof idx === "number"
  41. ? pathSeqments.slice(0, idx + 1)
  42. : pathSeqments.slice();
  43. const result = resultSeqments.reverse().reduce((a, b) => {
  44. return resolver.join(a, b);
  45. });
  46. const obj = Object.assign({}, request, {
  47. path: result
  48. });
  49. resolver.doResolve(
  50. target,
  51. obj,
  52. "resolved symlink to " + result,
  53. resolveContext,
  54. callback
  55. );
  56. }
  57. );
  58. });
  59. }
  60. };