| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 0c9efcc commit 24865bc
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -81,15 +81,12 @@ function getStats(src, dest, opts) { | |||
| 81 | 81 | ||
| 82 | 82 | function onFile(srcStat, destStat, src, dest, opts) { | |
| 83 | 83 | if (!destStat) return copyFile(srcStat, src, dest, opts); | |
| 84 | - return mayCopyFile(srcStat, src, dest, opts); | ||
| 85 | - } | ||
| 86 | 84 | ||
| 87 | - // TODO(@anonrig): Move this function to C++. | ||
| 88 | - function mayCopyFile(srcStat, src, dest, opts) { | ||
| 89 | 85 | if (opts.force) { | |
| 90 | - unlinkSync(dest); | ||
| 91 | - return copyFile(srcStat, src, dest, opts); | ||
| 92 | - } else if (opts.errorOnExist) { | ||
| 86 | + return fsBinding.cpSyncOverrideFile(src, dest, opts.mode, opts.preserveTimestamps); | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + if (opts.errorOnExist) { | ||
| 93 | 90 | throw new ERR_FS_CP_EEXIST({ | |
| 94 | 91 | message: `${dest} already exists`, | |
| 95 | 92 | path: dest, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -805,6 +805,13 @@ inline void Environment::ThrowError( | |||
| 805 | 805 | isolate()->ThrowException(fun(OneByteString(isolate(), errmsg), {})); | |
| 806 | 806 | } | |
| 807 | 807 | ||
| 808 | + inline void Environment::ThrowStdErrException(std::error_code error_code, | ||
| 809 | + const char* syscall, | ||
| 810 | + const char* path) { | ||
| 811 | + ThrowErrnoException( | ||
| 812 | + error_code.value(), syscall, error_code.message().c_str(), path); | ||
| 813 | + } | ||
| 814 | + | ||
| 808 | 815 | inline void Environment::ThrowErrnoException(int errorno, | |
| 809 | 816 | const char* syscall, | |
| 810 | 817 | const char* message, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -850,6 +850,9 @@ class Environment final : public MemoryRetainer { | |||
| 850 | 850 | inline void ThrowError(const char* errmsg); | |
| 851 | 851 | inline void ThrowTypeError(const char* errmsg); | |
| 852 | 852 | inline void ThrowRangeError(const char* errmsg); | |
| 853 | + inline void ThrowStdErrException(std::error_code error_code, | ||
| 854 | + const char* syscall, | ||
| 855 | + const char* path = nullptr); | ||
| 853 | 856 | inline void ThrowErrnoException(int errorno, | |
| 854 | 857 | const char* syscall = nullptr, | |
| 855 | 858 | const char* message = nullptr, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -42,6 +42,7 @@ | |||
| 42 | 42 | #include "uv.h" | |
| 43 | 43 | #include "v8-fast-api-calls.h" | |
| 44 | 44 | ||
| 45 | + #include <cstdio> | ||
| 45 | 46 | #include <filesystem> | |
| 46 | 47 | ||
| 47 | 48 | #if defined(__MINGW32__) || defined(_MSC_VER) | |
@@ -3236,6 +3237,72 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) { | |||
| 3236 | 3237 | } | |
| 3237 | 3238 | } | |
| 3238 | 3239 | ||
| 3240 | + static void CpSyncOverrideFile(const FunctionCallbackInfo<Value>& args) { | ||
| 3241 | + Environment* env = Environment::GetCurrent(args); | ||
| 3242 | + Isolate* isolate = env->isolate(); | ||
| 3243 | + | ||
| 3244 | + CHECK_EQ(args.Length(), 4); // src, dest, mode, preserveTimestamps | ||
| 3245 | + | ||
| 3246 | + BufferValue src(isolate, args[0]); | ||
| 3247 | + CHECK_NOT_NULL(*src); | ||
| 3248 | + ToNamespacedPath(env, &src); | ||
| 3249 | + | ||
| 3250 | + BufferValue dest(isolate, args[1]); | ||
| 3251 | + CHECK_NOT_NULL(*dest); | ||
| 3252 | + ToNamespacedPath(env, &dest); | ||
| 3253 | + | ||
| 3254 | + int mode; | ||
| 3255 | + if (!GetValidFileMode(env, args[2], UV_FS_COPYFILE).To(&mode)) { | ||
| 3256 | + return; | ||
| 3257 | + } | ||
| 3258 | + | ||
| 3259 | + bool preserve_timestamps = args[3]->IsTrue(); | ||
| 3260 | + | ||
| 3261 | + THROW_IF_INSUFFICIENT_PERMISSIONS( | ||
| 3262 | + env, permission::PermissionScope::kFileSystemRead, src.ToStringView()); | ||
| 3263 | + THROW_IF_INSUFFICIENT_PERMISSIONS( | ||
| 3264 | + env, permission::PermissionScope::kFileSystemWrite, dest.ToStringView()); | ||
| 3265 | + | ||
| 3266 | + std::error_code error; | ||
| 3267 | + | ||
| 3268 | + if (!std::filesystem::remove(*dest, error)) { | ||
| 3269 | + return env->ThrowStdErrException(error, "unlink", *dest); | ||
| 3270 | + } | ||
| 3271 | + | ||
| 3272 | + if (mode == 0) { | ||
| 3273 | + // if no mode is specified use the faster std::filesystem API | ||
| 3274 | + if (!std::filesystem::copy_file(*src, *dest, error)) { | ||
| 3275 | + return env->ThrowStdErrException(error, "cp", *dest); | ||
| 3276 | + } | ||
| 3277 | + } else { | ||
| 3278 | + uv_fs_t req; | ||
| 3279 | + auto cleanup = OnScopeLeave([&req]() { uv_fs_req_cleanup(&req); }); | ||
| 3280 | + auto result = uv_fs_copyfile(nullptr, &req, *src, *dest, mode, nullptr); | ||
| 3281 | + if (is_uv_error(result)) { | ||
| 3282 | + return env->ThrowUVException(result, "cp", nullptr, *src, *dest); | ||
| 3283 | + } | ||
| 3284 | + } | ||
| 3285 | + | ||
| 3286 | + if (preserve_timestamps) { | ||
| 3287 | + uv_fs_t req; | ||
| 3288 | + auto cleanup = OnScopeLeave([&req]() { uv_fs_req_cleanup(&req); }); | ||
| 3289 | + int result = uv_fs_stat(nullptr, &req, *src, nullptr); | ||
| 3290 | + if (is_uv_error(result)) { | ||
| 3291 | + return env->ThrowUVException(result, "stat", nullptr, *src); | ||
| 3292 | + } | ||
| 3293 | + | ||
| 3294 | + const uv_stat_t* const s = static_cast<const uv_stat_t*>(req.ptr); | ||
| 3295 | + const double source_atime = s->st_atim.tv_sec + s->st_atim.tv_nsec / 1e9; | ||
| 3296 | + const double source_mtime = s->st_mtim.tv_sec + s->st_mtim.tv_nsec / 1e9; | ||
| 3297 | + | ||
| 3298 | + int utime_result = | ||
| 3299 | + uv_fs_utime(nullptr, &req, *dest, source_atime, source_mtime, nullptr); | ||
| 3300 | + if (is_uv_error(utime_result)) { | ||
| 3301 | + return env->ThrowUVException(utime_result, "utime", nullptr, *dest); | ||
| 3302 | + } | ||
| 3303 | + } | ||
| 3304 | + } | ||
| 3305 | + | ||
| 3239 | 3306 | BindingData::FilePathIsFileReturnType BindingData::FilePathIsFile( | |
| 3240 | 3307 | Environment* env, const std::string& file_path) { | |
| 3241 | 3308 | THROW_IF_INSUFFICIENT_PERMISSIONS( | |
@@ -3574,6 +3641,7 @@ static void CreatePerIsolateProperties(IsolateData* isolate_data, | |||
| 3574 | 3641 | SetMethod(isolate, target, "mkdtemp", Mkdtemp); | |
| 3575 | 3642 | ||
| 3576 | 3643 | SetMethod(isolate, target, "cpSyncCheckPaths", CpSyncCheckPaths); | |
| 3644 | + SetMethod(isolate, target, "cpSyncOverrideFile", CpSyncOverrideFile); | ||
| 3577 | 3645 | ||
| 3578 | 3646 | StatWatcher::CreatePerIsolateProperties(isolate_data, target); | |
| 3579 | 3647 | BindingData::CreatePerIsolateProperties(isolate_data, target); | |
@@ -3685,6 +3753,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { | |||
| 3685 | 3753 | registry->Register(CopyFile); | |
| 3686 | 3754 | ||
| 3687 | 3755 | registry->Register(CpSyncCheckPaths); | |
| 3756 | + registry->Register(CpSyncOverrideFile); | ||
| 3688 | 3757 | ||
| 3689 | 3758 | registry->Register(Chmod); | |
| 3690 | 3759 | registry->Register(FChmod); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -77,6 +77,7 @@ declare namespace InternalFSBinding { | |||
| 77 | 77 | function copyFile(src: StringOrBuffer, dest: StringOrBuffer, mode: number, usePromises: typeof kUsePromises): Promise<void>; | |
| 78 | 78 | ||
| 79 | 79 | function cpSyncCheckPaths(src: StringOrBuffer, dest: StringOrBuffer, dereference: boolean, recursive: boolean): void; | |
| 80 | + function cpSyncOverrideFile(src: StringOrBuffer, dest: StringOrBuffer, mode: number, preserveTimestamps: boolean): void; | ||
| 80 | 81 | ||
| 81 | 82 | function fchmod(fd: number, mode: number, req: FSReqCallback): void; | |
| 82 | 83 | function fchmod(fd: number, mode: number): void; | |
@@ -258,6 +259,7 @@ export interface FsBinding { | |||
| 258 | 259 | close: typeof InternalFSBinding.close; | |
| 259 | 260 | copyFile: typeof InternalFSBinding.copyFile; | |
| 260 | 261 | cpSyncCheckPaths: typeof InternalFSBinding.cpSyncCheckPaths; | |
| 262 | + cpSyncOverrideFile: typeof InternalFSBinding.cpSyncOverrideFile; | ||
| 261 | 263 | fchmod: typeof InternalFSBinding.fchmod; | |
| 262 | 264 | fchown: typeof InternalFSBinding.fchown; | |
| 263 | 265 | fdatasync: typeof InternalFSBinding.fdatasync; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments