symlink.js 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. 'use strict'
  2. const u = require('universalify').fromCallback
  3. const path = require('path')
  4. const fs = require('../fs')
  5. const _mkdirs = require('../mkdirs')
  6. const mkdirs = _mkdirs.mkdirs
  7. const mkdirsSync = _mkdirs.mkdirsSync
  8. const _symlinkPaths = require('./symlink-paths')
  9. const symlinkPaths = _symlinkPaths.symlinkPaths
  10. const symlinkPathsSync = _symlinkPaths.symlinkPathsSync
  11. const _symlinkType = require('./symlink-type')
  12. const symlinkType = _symlinkType.symlinkType
  13. const symlinkTypeSync = _symlinkType.symlinkTypeSync
  14. const pathExists = require('../path-exists').pathExists
  15. const { areIdentical } = require('../util/stat')
  16. function createSymlink (srcpath, dstpath, type, callback) {
  17. callback = (typeof type === 'function') ? type : callback
  18. type = (typeof type === 'function') ? false : type
  19. fs.lstat(dstpath, (err, stats) => {
  20. if (!err && stats.isSymbolicLink()) {
  21. Promise.all([
  22. fs.stat(srcpath),
  23. fs.stat(dstpath)
  24. ]).then(([srcStat, dstStat]) => {
  25. if (areIdentical(srcStat, dstStat)) return callback(null)
  26. _createSymlink(srcpath, dstpath, type, callback)
  27. })
  28. } else _createSymlink(srcpath, dstpath, type, callback)
  29. })
  30. }
  31. function _createSymlink (srcpath, dstpath, type, callback) {
  32. symlinkPaths(srcpath, dstpath, (err, relative) => {
  33. if (err) return callback(err)
  34. srcpath = relative.toDst
  35. symlinkType(relative.toCwd, type, (err, type) => {
  36. if (err) return callback(err)
  37. const dir = path.dirname(dstpath)
  38. pathExists(dir, (err, dirExists) => {
  39. if (err) return callback(err)
  40. if (dirExists) return fs.symlink(srcpath, dstpath, type, callback)
  41. mkdirs(dir, err => {
  42. if (err) return callback(err)
  43. fs.symlink(srcpath, dstpath, type, callback)
  44. })
  45. })
  46. })
  47. })
  48. }
  49. function createSymlinkSync (srcpath, dstpath, type) {
  50. let stats
  51. try {
  52. stats = fs.lstatSync(dstpath)
  53. } catch {}
  54. if (stats && stats.isSymbolicLink()) {
  55. const srcStat = fs.statSync(srcpath)
  56. const dstStat = fs.statSync(dstpath)
  57. if (areIdentical(srcStat, dstStat)) return
  58. }
  59. const relative = symlinkPathsSync(srcpath, dstpath)
  60. srcpath = relative.toDst
  61. type = symlinkTypeSync(relative.toCwd, type)
  62. const dir = path.dirname(dstpath)
  63. const exists = fs.existsSync(dir)
  64. if (exists) return fs.symlinkSync(srcpath, dstpath, type)
  65. mkdirsSync(dir)
  66. return fs.symlinkSync(srcpath, dstpath, type)
  67. }
  68. module.exports = {
  69. createSymlink: u(createSymlink),
  70. createSymlinkSync
  71. }