write-symbolic-link.js 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. 'use strict';
  2. var os = require('os');
  3. var path = require('path');
  4. var fo = require('../../file-operations');
  5. var isWindows = (os.platform() === 'win32');
  6. function writeSymbolicLink(file, optResolver, onWritten) {
  7. if (!file.symlink) {
  8. return onWritten(new Error('Missing symlink property on symbolic vinyl'));
  9. }
  10. var isRelative = optResolver.resolve('relativeSymlinks', file);
  11. var flags = fo.getFlags({
  12. overwrite: optResolver.resolve('overwrite', file),
  13. append: optResolver.resolve('append', file),
  14. });
  15. if (!isWindows) {
  16. // On non-Windows, just use 'file'
  17. return createLinkWithType('file');
  18. }
  19. fo.reflectStat(file.symlink, file, onReflect);
  20. function onReflect(statErr) {
  21. if (statErr && statErr.code !== 'ENOENT') {
  22. return onWritten(statErr);
  23. }
  24. // This option provides a way to create a Junction instead of a
  25. // Directory symlink on Windows. This comes with the following caveats:
  26. // * NTFS Junctions cannot be relative.
  27. // * NTFS Junctions MUST be directories.
  28. // * NTFS Junctions must be on the same file system.
  29. // * Most products CANNOT detect a directory is a Junction:
  30. // This has the side effect of possibly having a whole directory
  31. // deleted when a product is deleting the Junction directory.
  32. // For example, JetBrains product lines will delete the entire contents
  33. // of the TARGET directory because the product does not realize it's
  34. // a symlink as the JVM and Node return false for isSymlink.
  35. // This function is Windows only, so we don't need to check again
  36. var useJunctions = optResolver.resolve('useJunctions', file);
  37. var dirType = useJunctions ? 'junction' : 'dir';
  38. // Dangling links are always 'file'
  39. var type = !statErr && file.isDirectory() ? dirType : 'file';
  40. createLinkWithType(type);
  41. }
  42. function createLinkWithType(type) {
  43. // This is done after prepare() to use the adjusted file.base property
  44. if (isRelative && type !== 'junction') {
  45. file.symlink = path.relative(file.base, file.symlink);
  46. }
  47. var opts = {
  48. flags: flags,
  49. type: type,
  50. };
  51. fo.symlink(file.symlink, file.path, opts, onSymlink);
  52. function onSymlink(symlinkErr) {
  53. if (symlinkErr) {
  54. return onWritten(symlinkErr);
  55. }
  56. fo.reflectLinkStat(file.path, file, onWritten);
  57. }
  58. }
  59. }
  60. module.exports = writeSymbolicLink;