source: trip-planner-front/node_modules/@npmcli/move-file/index.js@ 6a3a178

Last change on this file since 6a3a178 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 4.5 KB
Line 
1const { dirname, join, resolve, relative, isAbsolute } = require('path')
2const rimraf_ = require('rimraf')
3const { promisify } = require('util')
4const {
5 access: access_,
6 accessSync,
7 copyFile: copyFile_,
8 copyFileSync,
9 unlink: unlink_,
10 unlinkSync,
11 readdir: readdir_,
12 readdirSync,
13 rename: rename_,
14 renameSync,
15 stat: stat_,
16 statSync,
17 lstat: lstat_,
18 lstatSync,
19 symlink: symlink_,
20 symlinkSync,
21 readlink: readlink_,
22 readlinkSync
23} = require('fs')
24
25const access = promisify(access_)
26const copyFile = promisify(copyFile_)
27const unlink = promisify(unlink_)
28const readdir = promisify(readdir_)
29const rename = promisify(rename_)
30const stat = promisify(stat_)
31const lstat = promisify(lstat_)
32const symlink = promisify(symlink_)
33const readlink = promisify(readlink_)
34const rimraf = promisify(rimraf_)
35const rimrafSync = rimraf_.sync
36
37const mkdirp = require('mkdirp')
38
39const pathExists = async path => {
40 try {
41 await access(path)
42 return true
43 } catch (er) {
44 return er.code !== 'ENOENT'
45 }
46}
47
48const pathExistsSync = path => {
49 try {
50 accessSync(path)
51 return true
52 } catch (er) {
53 return er.code !== 'ENOENT'
54 }
55}
56
57const moveFile = async (source, destination, options = {}, root = true, symlinks = []) => {
58 if (!source || !destination) {
59 throw new TypeError('`source` and `destination` file required')
60 }
61
62 options = {
63 overwrite: true,
64 ...options
65 }
66
67 if (!options.overwrite && await pathExists(destination)) {
68 throw new Error(`The destination file exists: ${destination}`)
69 }
70
71 await mkdirp(dirname(destination))
72
73 try {
74 await rename(source, destination)
75 } catch (error) {
76 if (error.code === 'EXDEV' || error.code === 'EPERM') {
77 const sourceStat = await lstat(source)
78 if (sourceStat.isDirectory()) {
79 const files = await readdir(source)
80 await Promise.all(files.map((file) => moveFile(join(source, file), join(destination, file), options, false, symlinks)))
81 } else if (sourceStat.isSymbolicLink()) {
82 symlinks.push({ source, destination })
83 } else {
84 await copyFile(source, destination)
85 }
86 } else {
87 throw error
88 }
89 }
90
91 if (root) {
92 await Promise.all(symlinks.map(async ({ source, destination }) => {
93 let target = await readlink(source)
94 // junction symlinks in windows will be absolute paths, so we need to make sure they point to the destination
95 if (isAbsolute(target))
96 target = resolve(destination, relative(source, target))
97 // try to determine what the actual file is so we can create the correct type of symlink in windows
98 let targetStat
99 try {
100 targetStat = await stat(resolve(dirname(source), target))
101 } catch (err) {}
102 await symlink(target, destination, targetStat && targetStat.isDirectory() ? 'junction' : 'file')
103 }))
104 await rimraf(source)
105 }
106}
107
108const moveFileSync = (source, destination, options = {}, root = true, symlinks = []) => {
109 if (!source || !destination) {
110 throw new TypeError('`source` and `destination` file required')
111 }
112
113 options = {
114 overwrite: true,
115 ...options
116 }
117
118 if (!options.overwrite && pathExistsSync(destination)) {
119 throw new Error(`The destination file exists: ${destination}`)
120 }
121
122 mkdirp.sync(dirname(destination))
123
124 try {
125 renameSync(source, destination)
126 } catch (error) {
127 if (error.code === 'EXDEV' || error.code === 'EPERM') {
128 const sourceStat = lstatSync(source)
129 if (sourceStat.isDirectory()) {
130 const files = readdirSync(source)
131 for (const file of files) {
132 moveFileSync(join(source, file), join(destination, file), options, false, symlinks)
133 }
134 } else if (sourceStat.isSymbolicLink()) {
135 symlinks.push({ source, destination })
136 } else {
137 copyFileSync(source, destination)
138 }
139 } else {
140 throw error
141 }
142 }
143
144 if (root) {
145 for (const { source, destination } of symlinks) {
146 let target = readlinkSync(source)
147 // junction symlinks in windows will be absolute paths, so we need to make sure they point to the destination
148 if (isAbsolute(target))
149 target = resolve(destination, relative(source, target))
150 // try to determine what the actual file is so we can create the correct type of symlink in windows
151 let targetStat
152 try {
153 targetStat = statSync(resolve(dirname(source), target))
154 } catch (err) {}
155 symlinkSync(target, destination, targetStat && targetStat.isDirectory() ? 'junction' : 'file')
156 }
157 rimrafSync(source)
158 }
159}
160
161module.exports = moveFile
162module.exports.sync = moveFileSync
Note: See TracBrowser for help on using the repository browser.