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.
		
		
		
		
		
			
		
			
				
					100 lines
				
				3.3 KiB
			
		
		
			
		
	
	
					100 lines
				
				3.3 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								'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
							 | 
						||
| 
								 | 
							
								}
							 |