100 lines
3.3 KiB
JavaScript
100 lines
3.3 KiB
JavaScript
'use strict'
|
|
|
|
const path = require('path')
|
|
const fs = require('graceful-fs')
|
|
const pathExists = require('../path-exists').pathExists
|
|
|
|
/**
|
|
* Function that returns two types of paths, one relative to symlink, and one
|
|
* relative to the current working directory. Checks if path is absolute or
|
|
* relative. If the path is relative, this function checks if the path is
|
|
* relative to symlink or relative to current working directory. This is an
|
|
* initiative to find a smarter `srcpath` to supply when building symlinks.
|
|
* This allows you to determine which path to use out of one of three possible
|
|
* types of source paths. The first is an absolute path. This is detected by
|
|
* `path.isAbsolute()`. When an absolute path is provided, it is checked to
|
|
* see if it exists. If it does it's used, if not an error is returned
|
|
* (callback)/ thrown (sync). The other two options for `srcpath` are a
|
|
* relative url. By default Node's `fs.symlink` works by creating a symlink
|
|
* using `dstpath` and expects the `srcpath` to be relative to the newly
|
|
* created symlink. If you provide a `srcpath` that does not exist on the file
|
|
* system it results in a broken symlink. To minimize this, the function
|
|
* checks to see if the 'relative to symlink' source file exists, and if it
|
|
* does it will use it. If it does not, it checks if there's a file that
|
|
* exists that is relative to the current working directory, if does its used.
|
|
* This preserves the expectations of the original fs.symlink spec and adds
|
|
* the ability to pass in `relative to current working direcotry` paths.
|
|
*/
|
|
|
|
function symlinkPaths (srcpath, dstpath, callback) {
|
|
if (path.isAbsolute(srcpath)) {
|
|
return fs.lstat(srcpath, (err) => {
|
|
if (err) {
|
|
err.message = err.message.replace('lstat', 'ensureSymlink')
|
|
return callback(err)
|
|
}
|
|
return callback(null, {
|
|
toCwd: srcpath,
|
|
toDst: srcpath
|
|
})
|
|
})
|
|
} else {
|
|
const dstdir = path.dirname(dstpath)
|
|
const relativeToDst = path.join(dstdir, srcpath)
|
|
return pathExists(relativeToDst, (err, exists) => {
|
|
if (err) return callback(err)
|
|
if (exists) {
|
|
return callback(null, {
|
|
toCwd: relativeToDst,
|
|
toDst: srcpath
|
|
})
|
|
} else {
|
|
return fs.lstat(srcpath, (err) => {
|
|
if (err) {
|
|
err.message = err.message.replace('lstat', 'ensureSymlink')
|
|
return callback(err)
|
|
}
|
|
return callback(null, {
|
|
toCwd: srcpath,
|
|
toDst: path.relative(dstdir, srcpath)
|
|
})
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
function symlinkPathsSync (srcpath, dstpath) {
|
|
let exists
|
|
if (path.isAbsolute(srcpath)) {
|
|
exists = fs.existsSync(srcpath)
|
|
if (!exists) throw new Error('absolute srcpath does not exist')
|
|
return {
|
|
toCwd: srcpath,
|
|
toDst: srcpath
|
|
}
|
|
} else {
|
|
const dstdir = path.dirname(dstpath)
|
|
const relativeToDst = path.join(dstdir, srcpath)
|
|
exists = fs.existsSync(relativeToDst)
|
|
if (exists) {
|
|
return {
|
|
toCwd: relativeToDst,
|
|
toDst: srcpath
|
|
}
|
|
} else {
|
|
exists = fs.existsSync(srcpath)
|
|
if (!exists) throw new Error('relative srcpath does not exist')
|
|
return {
|
|
toCwd: srcpath,
|
|
toDst: path.relative(dstdir, srcpath)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
symlinkPaths,
|
|
symlinkPathsSync
|
|
}
|