98 lines
3.4 KiB
JavaScript
98 lines
3.4 KiB
JavaScript
var path = require('path')
|
|
// path.isAbsolute shim for Node.js 0.10 support
|
|
path.isAbsolute = (path.isAbsolute) ? path.isAbsolute : require('path-is-absolute')
|
|
var fs = require('graceful-fs')
|
|
|
|
/**
|
|
* 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, function (err, stat) {
|
|
if (err) {
|
|
err.message = err.message.replace('lstat', 'ensureSymlink')
|
|
return callback(err)
|
|
}
|
|
return callback(null, {
|
|
'toCwd': srcpath,
|
|
'toDst': srcpath
|
|
})
|
|
})
|
|
} else {
|
|
var dstdir = path.dirname(dstpath)
|
|
var relativeToDst = path.join(dstdir, srcpath)
|
|
return fs.exists(relativeToDst, function (exists) {
|
|
if (exists) {
|
|
return callback(null, {
|
|
'toCwd': relativeToDst,
|
|
'toDst': srcpath
|
|
})
|
|
} else {
|
|
return fs.lstat(srcpath, function (err, stat) {
|
|
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) {
|
|
var 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 {
|
|
var dstdir = path.dirname(dstpath)
|
|
var 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': symlinkPaths,
|
|
'symlinkPathsSync': symlinkPathsSync
|
|
}
|