You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
3.3 KiB
99 lines
3.3 KiB
'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, stat) => { |
|
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, 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) { |
|
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 |
|
}
|
|
|