link.js 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. 'use strict'
  2. const u = require('universalify').fromCallback
  3. const path = require('path')
  4. const fs = require('graceful-fs')
  5. const mkdir = require('../mkdirs')
  6. const pathExists = require('../path-exists').pathExists
  7. const { areIdentical } = require('../util/stat')
  8. function createLink (srcpath, dstpath, callback) {
  9. function makeLink (srcpath, dstpath) {
  10. fs.link(srcpath, dstpath, err => {
  11. if (err) return callback(err)
  12. callback(null)
  13. })
  14. }
  15. fs.lstat(dstpath, (_, dstStat) => {
  16. fs.lstat(srcpath, (err, srcStat) => {
  17. if (err) {
  18. err.message = err.message.replace('lstat', 'ensureLink')
  19. return callback(err)
  20. }
  21. if (dstStat && areIdentical(srcStat, dstStat)) return callback(null)
  22. const dir = path.dirname(dstpath)
  23. pathExists(dir, (err, dirExists) => {
  24. if (err) return callback(err)
  25. if (dirExists) return makeLink(srcpath, dstpath)
  26. mkdir.mkdirs(dir, err => {
  27. if (err) return callback(err)
  28. makeLink(srcpath, dstpath)
  29. })
  30. })
  31. })
  32. })
  33. }
  34. function createLinkSync (srcpath, dstpath) {
  35. let dstStat
  36. try {
  37. dstStat = fs.lstatSync(dstpath)
  38. } catch {}
  39. try {
  40. const srcStat = fs.lstatSync(srcpath)
  41. if (dstStat && areIdentical(srcStat, dstStat)) return
  42. } catch (err) {
  43. err.message = err.message.replace('lstat', 'ensureLink')
  44. throw err
  45. }
  46. const dir = path.dirname(dstpath)
  47. const dirExists = fs.existsSync(dir)
  48. if (dirExists) return fs.linkSync(srcpath, dstpath)
  49. mkdir.mkdirsSync(dir)
  50. return fs.linkSync(srcpath, dstpath)
  51. }
  52. module.exports = {
  53. createLink: u(createLink),
  54. createLinkSync
  55. }