2
2
3
3
// This file is a modified version of the fs-extra's copySync method.
4
4
5
-
const { areIdentical, isSrcSubdir } = require('internal/fs/cp/cp');
5
+
const fsBinding = internalBinding('fs');
6
+
const { isSrcSubdir } = require('internal/fs/cp/cp');
6
7
const { codes: {
7
-
ERR_FS_CP_DIR_TO_NON_DIR,
8
8
ERR_FS_CP_EEXIST,
9
9
ERR_FS_CP_EINVAL,
10
-
ERR_FS_CP_FIFO_PIPE,
11
-
ERR_FS_CP_NON_DIR_TO_DIR,
12
-
ERR_FS_CP_SOCKET,
13
10
ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY,
14
-
ERR_FS_CP_UNKNOWN,
15
-
ERR_FS_EISDIR,
16
11
ERR_INVALID_RETURN_VALUE,
17
12
} } = require('internal/errors');
18
13
const {
19
14
os: {
20
15
errno: {
21
16
EEXIST,
22
-
EISDIR,
23
17
EINVAL,
24
-
ENOTDIR,
25
18
},
26
19
},
27
20
} = internalBinding('constants');
28
21
const {
29
22
chmodSync,
30
23
copyFileSync,
31
-
existsSync,
32
24
lstatSync,
33
25
mkdirSync,
34
26
opendirSync,
@@ -42,7 +34,6 @@ const {
42
34
dirname,
43
35
isAbsolute,
44
36
join,
45
-
parse,
46
37
resolve,
47
38
} = require('path');
48
39
const { isPromise } = require('util/types');
@@ -54,152 +45,46 @@ function cpSyncFn(src, dest, opts) {
54
45
'node is not recommended';
55
46
process.emitWarning(warning, 'TimestampPrecisionWarning');
56
47
}
57
-
const { srcStat, destStat, skipped } = checkPathsSync(src, dest, opts);
58
-
if (skipped) return;
59
-
checkParentPathsSync(src, srcStat, dest);
60
-
return checkParentDir(destStat, src, dest, opts);
61
-
}
62
-
63
-
function checkPathsSync(src, dest, opts) {
64
48
if (opts.filter) {
65
49
const shouldCopy = opts.filter(src, dest);
66
50
if (isPromise(shouldCopy)) {
67
51
throw new ERR_INVALID_RETURN_VALUE('boolean', 'filter', shouldCopy);
68
52
}
69
-
if (!shouldCopy) return { __proto__: null, skipped: true };
53
+
if (!shouldCopy) return;
70
54
}
71
-
const { srcStat, destStat } = getStatsSync(src, dest, opts);
72
55
73
-
if (destStat) {
74
-
if (areIdentical(srcStat, destStat)) {
75
-
throw new ERR_FS_CP_EINVAL({
76
-
message: 'src and dest cannot be the same',
77
-
path: dest,
78
-
syscall: 'cp',
79
-
errno: EINVAL,
80
-
code: 'EINVAL',
81
-
});
82
-
}
83
-
if (srcStat.isDirectory() && !destStat.isDirectory()) {
84
-
throw new ERR_FS_CP_DIR_TO_NON_DIR({
85
-
message: `cannot overwrite non-directory ${dest} ` +
86
-
`with directory ${src}`,
87
-
path: dest,
88
-
syscall: 'cp',
89
-
errno: EISDIR,
90
-
code: 'EISDIR',
91
-
});
92
-
}
93
-
if (!srcStat.isDirectory() && destStat.isDirectory()) {
94
-
throw new ERR_FS_CP_NON_DIR_TO_DIR({
95
-
message: `cannot overwrite directory ${dest} ` +
96
-
`with non-directory ${src}`,
97
-
path: dest,
98
-
syscall: 'cp',
99
-
errno: ENOTDIR,
100
-
code: 'ENOTDIR',
101
-
});
102
-
}
103
-
}
104
-
105
-
if (srcStat.isDirectory() && isSrcSubdir(src, dest)) {
106
-
throw new ERR_FS_CP_EINVAL({
107
-
message: `cannot copy ${src} to a subdirectory of self ${dest}`,
108
-
path: dest,
109
-
syscall: 'cp',
110
-
errno: EINVAL,
111
-
code: 'EINVAL',
112
-
});
113
-
}
114
-
return { __proto__: null, srcStat, destStat, skipped: false };
115
-
}
56
+
fsBinding.cpSyncCheckPaths(src, dest, opts.dereference, opts.recursive);
116
57
117
-
function getStatsSync(src, dest, opts) {
118
-
const statFunc = opts.dereference ? statSync : lstatSync;
119
-
const srcStat = statFunc(src, { bigint: true, throwIfNoEntry: true });
120
-
const destStat = statFunc(dest, { bigint: true, throwIfNoEntry: false });
121
-
return { srcStat, destStat };
58
+
return getStats(src, dest, opts);
122
59
}
123
60
124
-
function checkParentPathsSync(src, srcStat, dest) {
125
-
const srcParent = resolve(dirname(src));
126
-
const destParent = resolve(dirname(dest));
127
-
if (destParent === srcParent || destParent === parse(destParent).root) return;
128
-
const destStat = statSync(destParent, { bigint: true, throwIfNoEntry: false });
129
-
130
-
if (destStat === undefined) {
131
-
return;
132
-
}
133
-
134
-
if (areIdentical(srcStat, destStat)) {
135
-
throw new ERR_FS_CP_EINVAL({
136
-
message: `cannot copy ${src} to a subdirectory of self ${dest}`,
137
-
path: dest,
138
-
syscall: 'cp',
139
-
errno: EINVAL,
140
-
code: 'EINVAL',
141
-
});
142
-
}
143
-
return checkParentPathsSync(src, srcStat, destParent);
144
-
}
145
-
146
-
function checkParentDir(destStat, src, dest, opts) {
147
-
const destParent = dirname(dest);
148
-
if (!existsSync(destParent)) mkdirSync(destParent, { recursive: true });
149
-
return getStats(destStat, src, dest, opts);
150
-
}
151
-
152
-
function getStats(destStat, src, dest, opts) {
61
+
function getStats(src, dest, opts) {
62
+
// TODO(@anonrig): Avoid making two stat calls.
153
63
const statSyncFn = opts.dereference ? statSync : lstatSync;
154
64
const srcStat = statSyncFn(src);
65
+
const destStat = statSyncFn(dest, { bigint: true, throwIfNoEntry: false });
155
66
156
67
if (srcStat.isDirectory() && opts.recursive) {
157
68
return onDir(srcStat, destStat, src, dest, opts);
158
-
} else if (srcStat.isDirectory()) {
159
-
throw new ERR_FS_EISDIR({
160
-
message: `${src} is a directory (not copied)`,
161
-
path: src,
162
-
syscall: 'cp',
163
-
errno: EINVAL,
164
-
code: 'EISDIR',
165
-
});
166
69
} else if (srcStat.isFile() ||
167
70
srcStat.isCharacterDevice() ||
168
71
srcStat.isBlockDevice()) {
169
72
return onFile(srcStat, destStat, src, dest, opts);
170
73
} else if (srcStat.isSymbolicLink()) {
171
-
return onLink(destStat, src, dest, opts);
172
-
} else if (srcStat.isSocket()) {
173
-
throw new ERR_FS_CP_SOCKET({
174
-
message: `cannot copy a socket file: ${dest}`,
175
-
path: dest,
176
-
syscall: 'cp',
177
-
errno: EINVAL,
178
-
code: 'EINVAL',
179
-
});
180
-
} else if (srcStat.isFIFO()) {
181
-
throw new ERR_FS_CP_FIFO_PIPE({
182
-
message: `cannot copy a FIFO pipe: ${dest}`,
183
-
path: dest,
184
-
syscall: 'cp',
185
-
errno: EINVAL,
186
-
code: 'EINVAL',
187
-
});
74
+
return onLink(destStat, src, dest, opts.verbatimSymlinks);
188
75
}
189
-
throw new ERR_FS_CP_UNKNOWN({
190
-
message: `cannot copy an unknown file type: ${dest}`,
191
-
path: dest,
192
-
syscall: 'cp',
193
-
errno: EINVAL,
194
-
code: 'EINVAL',
195
-
});
76
+
77
+
// It is not possible to get here because all possible cases are handled above.
78
+
const assert = require('internal/assert');
79
+
assert.fail('Unreachable code');
196
80
}
197
81
198
82
function onFile(srcStat, destStat, src, dest, opts) {
199
83
if (!destStat) return copyFile(srcStat, src, dest, opts);
200
84
return mayCopyFile(srcStat, src, dest, opts);
201
85
}
202
86
87
+
// TODO(@anonrig): Move this function to C++.
203
88
function mayCopyFile(srcStat, src, dest, opts) {
204
89
if (opts.force) {
205
90
unlinkSync(dest);
@@ -249,6 +134,7 @@ function setDestTimestamps(src, dest) {
249
134
return utimesSync(dest, updatedSrcStat.atime, updatedSrcStat.mtime);
250
135
}
251
136
137
+
// TODO(@anonrig): Move this function to C++.
252
138
function onDir(srcStat, destStat, src, dest, opts) {
253
139
if (!destStat) return mkDirAndCopy(srcStat.mode, src, dest, opts);
254
140
return copyDir(src, dest, opts);
@@ -260,6 +146,7 @@ function mkDirAndCopy(srcMode, src, dest, opts) {
260
146
return setDestMode(dest, srcMode);
261
147
}
262
148
149
+
// TODO(@anonrig): Move this function to C++.
263
150
function copyDir(src, dest, opts) {
264
151
const dir = opendirSync(src);
265
152
@@ -270,17 +157,28 @@ function copyDir(src, dest, opts) {
270
157
const { name } = dirent;
271
158
const srcItem = join(src, name);
272
159
const destItem = join(dest, name);
273
-
const { destStat, skipped } = checkPathsSync(srcItem, destItem, opts);
274
-
if (!skipped) getStats(destStat, srcItem, destItem, opts);
160
+
let shouldCopy = true;
161
+
162
+
if (opts.filter) {
163
+
shouldCopy = opts.filter(srcItem, destItem);
164
+
if (isPromise(shouldCopy)) {
165
+
throw new ERR_INVALID_RETURN_VALUE('boolean', 'filter', shouldCopy);
166
+
}
167
+
}
168
+
169
+
if (shouldCopy) {
170
+
getStats(srcItem, destItem, opts);
171
+
}
275
172
}
276
173
} finally {
277
174
dir.closeSync();
278
175
}
279
176
}
280
177
281
-
function onLink(destStat, src, dest, opts) {
178
+
// TODO(@anonrig): Move this function to C++.
179
+
function onLink(destStat, src, dest, verbatimSymlinks) {
282
180
let resolvedSrc = readlinkSync(src);
283
-
if (!opts.verbatimSymlinks && !isAbsolute(resolvedSrc)) {
181
+
if (!verbatimSymlinks && !isAbsolute(resolvedSrc)) {
284
182
resolvedSrc = resolve(dirname(src), resolvedSrc);
285
183
}
286
184
if (!destStat) {
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4