A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/nodejs/node/commit/fcef56cb05 below:

improve cpSync no-filter copyDir performance · nodejs/node@fcef56c · GitHub

43 43

#include "uv.h"

44 44

#include "v8-fast-api-calls.h"

45 45 46 +

#include <errno.h>

47 +

#include <cerrno>

46 48

#include <cstdio>

47 49

#include <filesystem>

48 50

@@ -3390,6 +3392,223 @@ static void CpSyncOverrideFile(const FunctionCallbackInfo<Value>& args) {

3390 3392

}

3391 3393

}

3392 3394 3395 +

std::vector<std::string> normalizePathToArray(

3396 +

const std::filesystem::path& path) {

3397 +

std::vector<std::string> parts;

3398 +

std::filesystem::path absPath = std::filesystem::absolute(path);

3399 +

for (const auto& part : absPath) {

3400 +

if (!part.empty()) parts.push_back(part.string());

3401 +

}

3402 +

return parts;

3403 +

}

3404 + 3405 +

bool isInsideDir(const std::filesystem::path& src,

3406 +

const std::filesystem::path& dest) {

3407 +

auto srcArr = normalizePathToArray(src);

3408 +

auto destArr = normalizePathToArray(dest);

3409 +

if (srcArr.size() > destArr.size()) return false;

3410 +

return std::equal(srcArr.begin(), srcArr.end(), destArr.begin());

3411 +

}

3412 + 3413 +

static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {

3414 +

CHECK_EQ(args.Length(), 7); // src, dest, force, dereference, errorOnExist,

3415 +

// verbatimSymlinks, preserveTimestamps

3416 + 3417 +

Environment* env = Environment::GetCurrent(args);

3418 +

Isolate* isolate = env->isolate();

3419 + 3420 +

BufferValue src(isolate, args[0]);

3421 +

CHECK_NOT_NULL(*src);

3422 +

ToNamespacedPath(env, &src);

3423 + 3424 +

BufferValue dest(isolate, args[1]);

3425 +

CHECK_NOT_NULL(*dest);

3426 +

ToNamespacedPath(env, &dest);

3427 + 3428 +

bool force = args[2]->IsTrue();

3429 +

bool dereference = args[3]->IsTrue();

3430 +

bool error_on_exist = args[4]->IsTrue();

3431 +

bool verbatim_symlinks = args[5]->IsTrue();

3432 +

bool preserve_timestamps = args[6]->IsTrue();

3433 + 3434 +

std::error_code error;

3435 +

std::filesystem::create_directories(*dest, error);

3436 +

if (error) {

3437 +

return env->ThrowStdErrException(error, "cp", *dest);

3438 +

}

3439 + 3440 +

auto file_copy_opts = std::filesystem::copy_options::recursive;

3441 +

if (force) {

3442 +

file_copy_opts |= std::filesystem::copy_options::overwrite_existing;

3443 +

} else if (error_on_exist) {

3444 +

file_copy_opts |= std::filesystem::copy_options::none;

3445 +

} else {

3446 +

file_copy_opts |= std::filesystem::copy_options::skip_existing;

3447 +

}

3448 + 3449 +

std::function<bool(std::filesystem::path, std::filesystem::path)>

3450 +

copy_dir_contents;

3451 +

copy_dir_contents = [verbatim_symlinks,

3452 +

&copy_dir_contents,

3453 +

&env,

3454 +

file_copy_opts,

3455 +

preserve_timestamps,

3456 +

force,

3457 +

error_on_exist,

3458 +

dereference,

3459 +

&isolate](std::filesystem::path src,

3460 +

std::filesystem::path dest) {

3461 +

std::error_code error;

3462 +

for (auto dir_entry : std::filesystem::directory_iterator(src)) {

3463 +

auto dest_file_path = dest / dir_entry.path().filename();

3464 +

auto dest_str = PathToString(dest);

3465 + 3466 +

if (dir_entry.is_symlink()) {

3467 +

if (verbatim_symlinks) {

3468 +

std::filesystem::copy_symlink(

3469 +

dir_entry.path(), dest_file_path, error);

3470 +

if (error) {

3471 +

env->ThrowStdErrException(error, "cp", dest_str.c_str());

3472 +

return false;

3473 +

}

3474 +

} else {

3475 +

auto symlink_target =

3476 +

std::filesystem::read_symlink(dir_entry.path().c_str(), error);

3477 +

if (error) {

3478 +

env->ThrowStdErrException(error, "cp", dest_str.c_str());

3479 +

return false;

3480 +

}

3481 + 3482 +

if (std::filesystem::exists(dest_file_path)) {

3483 +

if (std::filesystem::is_symlink((dest_file_path.c_str()))) {

3484 +

auto current_dest_symlink_target =

3485 +

std::filesystem::read_symlink(dest_file_path.c_str(), error);

3486 +

if (error) {

3487 +

env->ThrowStdErrException(error, "cp", dest_str.c_str());

3488 +

return false;

3489 +

}

3490 + 3491 +

if (!dereference &&

3492 +

std::filesystem::is_directory(symlink_target) &&

3493 +

isInsideDir(symlink_target, current_dest_symlink_target)) {

3494 +

std::string message =

3495 +

"Cannot copy %s to a subdirectory of self %s";

3496 +

THROW_ERR_FS_CP_EINVAL(env,

3497 +

message.c_str(),

3498 +

symlink_target.c_str(),

3499 +

current_dest_symlink_target.c_str());

3500 +

return false;

3501 +

}

3502 + 3503 +

// Prevent copy if src is a subdir of dest since unlinking

3504 +

// dest in this case would result in removing src contents

3505 +

// and therefore a broken symlink would be created.

3506 +

if (std::filesystem::is_directory(dest_file_path) &&

3507 +

isInsideDir(current_dest_symlink_target, symlink_target)) {

3508 +

std::string message = "cannot overwrite %s with %s";

3509 +

THROW_ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY(

3510 +

env,

3511 +

message.c_str(),

3512 +

current_dest_symlink_target.c_str(),

3513 +

symlink_target.c_str());

3514 +

return false;

3515 +

}

3516 + 3517 +

// symlinks get overridden by cp even if force: false, this is

3518 +

// being applied here for backward compatibility, but is it

3519 +

// correct? or is it a bug?

3520 +

std::filesystem::remove(dest_file_path, error);

3521 +

if (error) {

3522 +

env->ThrowStdErrException(error, "cp", dest_str.c_str());

3523 +

return false;

3524 +

}

3525 +

} else if (std::filesystem::is_regular_file(dest_file_path)) {

3526 +

if (!dereference || (!force && error_on_exist)) {

3527 +

auto dest_file_path_str = PathToString(dest_file_path);

3528 +

env->ThrowStdErrException(

3529 +

std::make_error_code(std::errc::file_exists),

3530 +

"cp",

3531 +

dest_file_path_str.c_str());

3532 +

return false;

3533 +

}

3534 +

}

3535 +

}

3536 +

auto symlink_target_absolute = std::filesystem::weakly_canonical(

3537 +

std::filesystem::absolute(src / symlink_target));

3538 +

if (dir_entry.is_directory()) {

3539 +

std::filesystem::create_directory_symlink(

3540 +

symlink_target_absolute, dest_file_path, error);

3541 +

} else {

3542 +

std::filesystem::create_symlink(

3543 +

symlink_target_absolute, dest_file_path, error);

3544 +

}

3545 +

if (error) {

3546 +

env->ThrowStdErrException(error, "cp", dest_str.c_str());

3547 +

return false;

3548 +

}

3549 +

}

3550 +

} else if (dir_entry.is_directory()) {

3551 +

auto entry_dir_path = src / dir_entry.path().filename();

3552 +

std::filesystem::create_directory(dest_file_path);

3553 +

auto success = copy_dir_contents(entry_dir_path, dest_file_path);

3554 +

if (!success) {

3555 +

return false;

3556 +

}

3557 +

} else if (dir_entry.is_regular_file()) {

3558 +

std::filesystem::copy_file(

3559 +

dir_entry.path(), dest_file_path, file_copy_opts, error);

3560 +

if (error) {

3561 +

if (error.value() == EEXIST) {

3562 +

THROW_ERR_FS_CP_EEXIST(isolate,

3563 +

"[ERR_FS_CP_EEXIST]: Target already exists: "

3564 +

"cp returned EEXIST (%s already exists)",

3565 +

dest_file_path.c_str());

3566 +

return false;

3567 +

}

3568 +

env->ThrowStdErrException(error, "cp", dest_str.c_str());

3569 +

return false;

3570 +

}

3571 + 3572 +

if (preserve_timestamps) {

3573 +

uv_fs_t req;

3574 +

auto cleanup = OnScopeLeave([&req]() { uv_fs_req_cleanup(&req); });

3575 + 3576 +

auto dir_entry_path_str = PathToString(dir_entry.path());

3577 +

int result =

3578 +

uv_fs_stat(nullptr, &req, dir_entry_path_str.c_str(), nullptr);

3579 +

if (is_uv_error(result)) {

3580 +

env->ThrowUVException(

3581 +

result, "stat", nullptr, dir_entry_path_str.c_str());

3582 +

return false;

3583 +

}

3584 + 3585 +

const uv_stat_t* const s = static_cast<const uv_stat_t*>(req.ptr);

3586 +

const double source_atime =

3587 +

s->st_atim.tv_sec + s->st_atim.tv_nsec / 1e9;

3588 +

const double source_mtime =

3589 +

s->st_mtim.tv_sec + s->st_mtim.tv_nsec / 1e9;

3590 + 3591 +

auto dest_file_path_str = PathToString(dest_file_path);

3592 +

int utime_result = uv_fs_utime(nullptr,

3593 +

&req,

3594 +

dest_file_path_str.c_str(),

3595 +

source_atime,

3596 +

source_mtime,

3597 +

nullptr);

3598 +

if (is_uv_error(utime_result)) {

3599 +

env->ThrowUVException(

3600 +

utime_result, "utime", nullptr, dest_file_path_str.c_str());

3601 +

return false;

3602 +

}

3603 +

}

3604 +

}

3605 +

}

3606 +

return true;

3607 +

};

3608 + 3609 +

copy_dir_contents(std::filesystem::path(*src), std::filesystem::path(*dest));

3610 +

}

3611 + 3393 3612

BindingData::FilePathIsFileReturnType BindingData::FilePathIsFile(

3394 3613

Environment* env, const std::string& file_path) {

3395 3614

THROW_IF_INSUFFICIENT_PERMISSIONS(

@@ -3726,6 +3945,7 @@ static void CreatePerIsolateProperties(IsolateData* isolate_data,

3726 3945 3727 3946

SetMethod(isolate, target, "cpSyncCheckPaths", CpSyncCheckPaths);

3728 3947

SetMethod(isolate, target, "cpSyncOverrideFile", CpSyncOverrideFile);

3948 +

SetMethod(isolate, target, "cpSyncCopyDir", CpSyncCopyDir);

3729 3949 3730 3950

StatWatcher::CreatePerIsolateProperties(isolate_data, target);

3731 3951

BindingData::CreatePerIsolateProperties(isolate_data, target);

@@ -3837,6 +4057,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {

3837 4057 3838 4058

registry->Register(CpSyncCheckPaths);

3839 4059

registry->Register(CpSyncOverrideFile);

4060 +

registry->Register(CpSyncCopyDir);

3840 4061 3841 4062

registry->Register(Chmod);

3842 4063

registry->Register(FChmod);


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