dsh-remote 0.8.46 → 0.8.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.en.md +361 -361
- package/README.md +368 -368
- package/cordis.patch.yml +9 -9
- package/lib/binding.js +172 -172
- package/lib/client.js +3637 -3637
- package/lib/credential.js +177 -177
- package/lib/deploy-tasks.js +142 -142
- package/lib/errors.js +87 -87
- package/lib/file-reference.js +457 -457
- package/lib/forwards.js +258 -258
- package/lib/hostkey.js +108 -108
- package/lib/http-transport.js +196 -196
- package/lib/ignore.js +202 -156
- package/lib/index.js +3779 -3747
- package/lib/openssh.js +838 -838
- package/lib/paths.js +225 -225
- package/lib/pool.js +757 -757
- package/lib/registry.js +95 -95
- package/lib/remote-fs.js +148 -143
- package/lib/routes-fs.js +233 -233
- package/lib/search.js +235 -230
- package/lib/sftp-surface.js +76 -76
- package/lib/sshconfig.js +454 -454
- package/lib/sync.js +275 -275
- package/lib/tasks.js +95 -95
- package/lib/telemetry.js +213 -213
- package/lib/update.js +472 -472
- package/lib/web-attach.js +850 -850
- package/lib/web-deploy-skill.js +205 -205
- package/lib/web-deploy.js +694 -694
- package/node_modules/asn1/Jenkinsfile +65 -0
- package/node_modules/asn1/LICENSE +19 -0
- package/node_modules/asn1/README.md +50 -0
- package/node_modules/asn1/lib/ber/errors.js +13 -0
- package/node_modules/asn1/lib/ber/index.js +27 -0
- package/node_modules/asn1/lib/ber/reader.js +262 -0
- package/node_modules/asn1/lib/ber/types.js +36 -0
- package/node_modules/asn1/lib/ber/writer.js +317 -0
- package/node_modules/asn1/lib/index.js +20 -0
- package/node_modules/asn1/package.json +31 -0
- package/node_modules/bcrypt-pbkdf/CONTRIBUTING.md +13 -0
- package/node_modules/bcrypt-pbkdf/LICENSE +66 -0
- package/node_modules/bcrypt-pbkdf/README.md +45 -0
- package/node_modules/bcrypt-pbkdf/index.js +556 -0
- package/node_modules/bcrypt-pbkdf/package.json +15 -0
- package/node_modules/buildcheck/.eslintrc.js +5 -0
- package/node_modules/buildcheck/.github/workflows/ci.yml +88 -0
- package/node_modules/buildcheck/.github/workflows/lint.yml +27 -0
- package/node_modules/buildcheck/.npmignore +3 -0
- package/node_modules/buildcheck/LICENSE +19 -0
- package/node_modules/buildcheck/README.md +106 -0
- package/node_modules/buildcheck/deps/Find-VisualStudio.cs +250 -0
- package/node_modules/buildcheck/lib/findvs.js +361 -0
- package/node_modules/buildcheck/lib/index.js +738 -0
- package/node_modules/buildcheck/package.json +36 -0
- package/node_modules/buildcheck/test/test.js +8 -0
- package/node_modules/cpu-features/.eslintrc.js +5 -0
- package/node_modules/cpu-features/.github/workflows/ci.yml +74 -0
- package/node_modules/cpu-features/.github/workflows/lint.yml +27 -0
- package/node_modules/cpu-features/LICENSE +19 -0
- package/node_modules/cpu-features/README.md +59 -0
- package/node_modules/cpu-features/binding.gyp +16 -0
- package/node_modules/cpu-features/buildcheck.js +32 -0
- package/node_modules/cpu-features/deps/cpu_features/.clang-format +4 -0
- package/node_modules/cpu-features/deps/cpu_features/.dockerignore +31 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/Dockerfile +5 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/aarch64_linux_cmake.yml +30 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/amd64_freebsd_cmake.yml +22 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/amd64_linux_bazel.yml +26 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/amd64_linux_cmake.yml +31 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/amd64_macos_cmake.yml +43 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/amd64_windows_cmake.yml +25 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/arm_linux_cmake.yml +31 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/clang_format.yml +24 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/mips_linux_cmake.yml +30 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/power_linux_cmake.yml +29 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/riscv_linux_cmake.yml +28 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/s390x_linux_cmake.yml +27 -0
- package/node_modules/cpu-features/deps/cpu_features/.grenrc.yml +21 -0
- package/node_modules/cpu-features/deps/cpu_features/BUILD.bazel +329 -0
- package/node_modules/cpu-features/deps/cpu_features/CMakeLists.txt +261 -0
- package/node_modules/cpu-features/deps/cpu_features/CONTRIBUTING.md +23 -0
- package/node_modules/cpu-features/deps/cpu_features/LICENSE +230 -0
- package/node_modules/cpu-features/deps/cpu_features/README.md +272 -0
- package/node_modules/cpu-features/deps/cpu_features/WORKSPACE +19 -0
- package/node_modules/cpu-features/deps/cpu_features/bazel/ci/README.md +5 -0
- package/node_modules/cpu-features/deps/cpu_features/bazel/platforms.bzl +11 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/CpuFeaturesConfig.cmake.in +3 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/CpuFeaturesNdkCompatConfig.cmake.in +3 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/README.md +30 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/Makefile +252 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/README.md +40 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/doc/docker.dot +64 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/doc/docker.svg +312 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/doc/generate_image.sh +7 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/docker/amd64/Dockerfile +48 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/docker/toolchain/Dockerfile +34 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/sample/CMakeLists.txt +22 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/sample/main.cpp +11 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/vagrant/freebsd/Vagrantfile +107 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/googletest.CMakeLists.txt.in +15 -0
- package/node_modules/cpu-features/deps/cpu_features/cpu_features.gyp +105 -0
- package/node_modules/cpu-features/deps/cpu_features/include/cpu_features_cache_info.h +54 -0
- package/node_modules/cpu-features/deps/cpu_features/include/cpu_features_macros.h +384 -0
- package/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_aarch64.h +259 -0
- package/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_arm.h +121 -0
- package/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_mips.h +74 -0
- package/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_ppc.h +149 -0
- package/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_riscv.h +72 -0
- package/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_s390x.h +108 -0
- package/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_x86.h +288 -0
- package/node_modules/cpu-features/deps/cpu_features/include/internal/bit_utils.h +40 -0
- package/node_modules/cpu-features/deps/cpu_features/include/internal/cpuid_x86.h +37 -0
- package/node_modules/cpu-features/deps/cpu_features/include/internal/filesystem.h +39 -0
- package/node_modules/cpu-features/deps/cpu_features/include/internal/hwcaps.h +240 -0
- package/node_modules/cpu-features/deps/cpu_features/include/internal/stack_line_reader.h +49 -0
- package/node_modules/cpu-features/deps/cpu_features/include/internal/string_view.h +110 -0
- package/node_modules/cpu-features/deps/cpu_features/include/internal/windows_utils.h +70 -0
- package/node_modules/cpu-features/deps/cpu_features/ndk_compat/CMakeLists.txt +60 -0
- package/node_modules/cpu-features/deps/cpu_features/ndk_compat/README.md +4 -0
- package/node_modules/cpu-features/deps/cpu_features/ndk_compat/cpu-features.c +205 -0
- package/node_modules/cpu-features/deps/cpu_features/ndk_compat/cpu-features.h +320 -0
- package/node_modules/cpu-features/deps/cpu_features/ndk_compat/ndk-compat-test.c +12 -0
- package/node_modules/cpu-features/deps/cpu_features/patches/0001-Add-Apple-Silicon-Support.patch +456 -0
- package/node_modules/cpu-features/deps/cpu_features/scripts/generate_badges.d +165 -0
- package/node_modules/cpu-features/deps/cpu_features/scripts/make_release.sh +75 -0
- package/node_modules/cpu-features/deps/cpu_features/scripts/run_integration.sh +490 -0
- package/node_modules/cpu-features/deps/cpu_features/scripts/test_integration.sh +79 -0
- package/node_modules/cpu-features/deps/cpu_features/src/copy.inl +19 -0
- package/node_modules/cpu-features/deps/cpu_features/src/define_introspection.inl +86 -0
- package/node_modules/cpu-features/deps/cpu_features/src/define_introspection_and_hwcaps.inl +26 -0
- package/node_modules/cpu-features/deps/cpu_features/src/equals.inl +22 -0
- package/node_modules/cpu-features/deps/cpu_features/src/filesystem.c +62 -0
- package/node_modules/cpu-features/deps/cpu_features/src/hwcaps.c +169 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_aarch64__base_implementation.inl +88 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_aarch64_linux_or_android.c +79 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_aarch64_macos_or_iphone.c +82 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_aarch64_windows.c +138 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_arm_linux_or_android.c +212 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_mips_linux_or_android.c +93 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_ppc_linux.c +163 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_riscv_linux.c +111 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_s390x_linux.c +120 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_x86__base_implementation.inl +2055 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_x86_freebsd.c +68 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_x86_linux_or_android.c +58 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_x86_macos.c +57 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_x86_windows.c +58 -0
- package/node_modules/cpu-features/deps/cpu_features/src/stack_line_reader.c +132 -0
- package/node_modules/cpu-features/deps/cpu_features/src/string_view.c +192 -0
- package/node_modules/cpu-features/deps/cpu_features/src/utils/list_cpu_features.c +461 -0
- package/node_modules/cpu-features/deps/cpu_features/test/CMakeLists.txt +114 -0
- package/node_modules/cpu-features/deps/cpu_features/test/bit_utils_test.cc +53 -0
- package/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_aarch64_test.cc +396 -0
- package/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_arm_test.cc +384 -0
- package/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_mips_test.cc +176 -0
- package/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_ppc_test.cc +131 -0
- package/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_riscv_test.cc +180 -0
- package/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_s390x_test.cc +82 -0
- package/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_x86_test.cc +1729 -0
- package/node_modules/cpu-features/deps/cpu_features/test/filesystem_for_testing.cc +103 -0
- package/node_modules/cpu-features/deps/cpu_features/test/filesystem_for_testing.h +61 -0
- package/node_modules/cpu-features/deps/cpu_features/test/hwcaps_for_testing.cc +52 -0
- package/node_modules/cpu-features/deps/cpu_features/test/hwcaps_for_testing.h +31 -0
- package/node_modules/cpu-features/deps/cpu_features/test/stack_line_reader_test.cc +132 -0
- package/node_modules/cpu-features/deps/cpu_features/test/string_view_test.cc +202 -0
- package/node_modules/cpu-features/lib/index.js +5 -0
- package/node_modules/cpu-features/package.json +40 -0
- package/node_modules/cpu-features/src/binding.cc +151 -0
- package/node_modules/cpu-features/test/test.js +12 -0
- package/node_modules/nan/.github/workflows/ci.yml +46 -0
- package/node_modules/nan/.pre-commit-config.yaml +8 -0
- package/node_modules/nan/CHANGELOG.md +605 -0
- package/node_modules/nan/CMakeLists.txt +138 -0
- package/node_modules/nan/LICENSE.md +9 -0
- package/node_modules/nan/README.md +457 -0
- package/node_modules/nan/doc/asyncworker.md +146 -0
- package/node_modules/nan/doc/buffers.md +54 -0
- package/node_modules/nan/doc/callback.md +76 -0
- package/node_modules/nan/doc/converters.md +41 -0
- package/node_modules/nan/doc/errors.md +226 -0
- package/node_modules/nan/doc/json.md +62 -0
- package/node_modules/nan/doc/maybe_types.md +583 -0
- package/node_modules/nan/doc/methods.md +689 -0
- package/node_modules/nan/doc/new.md +147 -0
- package/node_modules/nan/doc/node_misc.md +123 -0
- package/node_modules/nan/doc/object_wrappers.md +263 -0
- package/node_modules/nan/doc/persistent.md +296 -0
- package/node_modules/nan/doc/scopes.md +73 -0
- package/node_modules/nan/doc/script.md +58 -0
- package/node_modules/nan/doc/string_bytes.md +81 -0
- package/node_modules/nan/doc/v8_internals.md +211 -0
- package/node_modules/nan/doc/v8_misc.md +85 -0
- package/node_modules/nan/include_dirs.js +1 -0
- package/node_modules/nan/nan.h +3202 -0
- package/node_modules/nan/nan_callbacks.h +141 -0
- package/node_modules/nan/nan_callbacks_12_inl.h +730 -0
- package/node_modules/nan/nan_callbacks_pre_12_inl.h +528 -0
- package/node_modules/nan/nan_converters.h +72 -0
- package/node_modules/nan/nan_converters_43_inl.h +68 -0
- package/node_modules/nan/nan_converters_pre_43_inl.h +42 -0
- package/node_modules/nan/nan_define_own_property_helper.h +29 -0
- package/node_modules/nan/nan_implementation_12_inl.h +446 -0
- package/node_modules/nan/nan_implementation_pre_12_inl.h +263 -0
- package/node_modules/nan/nan_json.h +166 -0
- package/node_modules/nan/nan_maybe_43_inl.h +360 -0
- package/node_modules/nan/nan_maybe_pre_43_inl.h +268 -0
- package/node_modules/nan/nan_new.h +340 -0
- package/node_modules/nan/nan_object_wrap.h +156 -0
- package/node_modules/nan/nan_persistent_12_inl.h +132 -0
- package/node_modules/nan/nan_persistent_pre_12_inl.h +242 -0
- package/node_modules/nan/nan_private.h +73 -0
- package/node_modules/nan/nan_scriptorigin.h +97 -0
- package/node_modules/nan/nan_string_bytes.h +305 -0
- package/node_modules/nan/nan_typedarray_contents.h +96 -0
- package/node_modules/nan/nan_weak.h +453 -0
- package/node_modules/nan/package.json +38 -0
- package/node_modules/nan/tools/1to2.js +412 -0
- package/node_modules/nan/tools/README.md +14 -0
- package/node_modules/nan/tools/package.json +19 -0
- package/node_modules/safer-buffer/LICENSE +21 -0
- package/node_modules/safer-buffer/Porting-Buffer.md +268 -0
- package/node_modules/safer-buffer/Readme.md +156 -0
- package/node_modules/safer-buffer/dangerous.js +58 -0
- package/node_modules/safer-buffer/package.json +34 -0
- package/node_modules/safer-buffer/safer.js +77 -0
- package/node_modules/safer-buffer/tests.js +406 -0
- package/node_modules/ssh2/.eslintignore +4 -0
- package/node_modules/ssh2/.eslintrc.js +5 -0
- package/node_modules/ssh2/.github/workflows/ci.yml +110 -0
- package/node_modules/ssh2/.github/workflows/lint.yml +27 -0
- package/node_modules/ssh2/LICENSE +19 -0
- package/node_modules/ssh2/README.md +1529 -0
- package/node_modules/ssh2/SFTP.md +413 -0
- package/node_modules/ssh2/examples/server-chat.js +238 -0
- package/node_modules/ssh2/examples/sftp-server-download-only.js +134 -0
- package/node_modules/ssh2/install.js +27 -0
- package/node_modules/ssh2/lib/Channel.js +295 -0
- package/node_modules/ssh2/lib/agent.js +1123 -0
- package/node_modules/ssh2/lib/client.js +2176 -0
- package/node_modules/ssh2/lib/http-agents.js +84 -0
- package/node_modules/ssh2/lib/index.js +44 -0
- package/node_modules/ssh2/lib/keygen.js +582 -0
- package/node_modules/ssh2/lib/protocol/Protocol.js +2136 -0
- package/node_modules/ssh2/lib/protocol/SFTP.js +4052 -0
- package/node_modules/ssh2/lib/protocol/constants.js +356 -0
- package/node_modules/ssh2/lib/protocol/crypto/binding.gyp +23 -0
- package/node_modules/ssh2/lib/protocol/crypto/poly1305.js +43 -0
- package/node_modules/ssh2/lib/protocol/crypto/src/binding.cc +2300 -0
- package/node_modules/ssh2/lib/protocol/crypto.js +1602 -0
- package/node_modules/ssh2/lib/protocol/handlers.js +16 -0
- package/node_modules/ssh2/lib/protocol/handlers.misc.js +1285 -0
- package/node_modules/ssh2/lib/protocol/kex.js +1908 -0
- package/node_modules/ssh2/lib/protocol/keyParser.js +1484 -0
- package/node_modules/ssh2/lib/protocol/node-fs-compat.js +115 -0
- package/node_modules/ssh2/lib/protocol/utils.js +356 -0
- package/node_modules/ssh2/lib/protocol/zlib.js +255 -0
- package/node_modules/ssh2/lib/server.js +1380 -0
- package/node_modules/ssh2/lib/utils.js +336 -0
- package/node_modules/ssh2/package.json +49 -0
- package/node_modules/ssh2/test/common.js +316 -0
- package/node_modules/ssh2/test/fixtures/bad_rsa_private_key +26 -0
- package/node_modules/ssh2/test/fixtures/https_cert.pem +33 -0
- package/node_modules/ssh2/test/fixtures/https_key.pem +52 -0
- package/node_modules/ssh2/test/fixtures/id_dsa +12 -0
- package/node_modules/ssh2/test/fixtures/id_ecdsa +5 -0
- package/node_modules/ssh2/test/fixtures/id_rsa +15 -0
- package/node_modules/ssh2/test/fixtures/id_rsa.ppk +26 -0
- package/node_modules/ssh2/test/fixtures/id_rsa_enc +30 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa +21 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc +22 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm +23 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa +9 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc +10 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc.pub.result +8 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm +10 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm.pub.result +8 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519 +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa +27 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc +28 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc.pub.result +8 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm +29 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm.pub.result +8 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa +12 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc +15 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc.pub.result +8 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa +5 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc +8 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc.pub.result +8 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa +27 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc +30 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc.pub.result +8 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256 +54 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256.pub.result +6 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256.result +6 -0
- package/node_modules/ssh2/test/fixtures/keyParser/ppk_dsa_enc +17 -0
- package/node_modules/ssh2/test/fixtures/keyParser/ppk_dsa_enc.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa +26 -0
- package/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa_enc +18 -0
- package/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa_enc.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa.pub +9 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa2.pub +10 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa2.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa3.pub +11 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa3.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa4.pub +11 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa4.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa5.pub +8 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa5.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa6.pub +13 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa6.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/openssh_new_rsa +27 -0
- package/node_modules/ssh2/test/fixtures/ssh_host_dsa_key +12 -0
- package/node_modules/ssh2/test/fixtures/ssh_host_ecdsa_key +5 -0
- package/node_modules/ssh2/test/fixtures/ssh_host_rsa_key +15 -0
- package/node_modules/ssh2/test/test-exec.js +578 -0
- package/node_modules/ssh2/test/test-integration-openssh.js +486 -0
- package/node_modules/ssh2/test/test-keygen.js +60 -0
- package/node_modules/ssh2/test/test-misc-client-server.js +1460 -0
- package/node_modules/ssh2/test/test-openssh.js +261 -0
- package/node_modules/ssh2/test/test-protocol-crypto.js +631 -0
- package/node_modules/ssh2/test/test-protocol-keyparser.js +177 -0
- package/node_modules/ssh2/test/test-server-hostkeys.js +138 -0
- package/node_modules/ssh2/test/test-sftp.js +842 -0
- package/node_modules/ssh2/test/test-shell.js +109 -0
- package/node_modules/ssh2/test/test-userauth-agent-openssh.js +110 -0
- package/node_modules/ssh2/test/test-userauth-agent.js +171 -0
- package/node_modules/ssh2/test/test-userauth.js +611 -0
- package/node_modules/ssh2/test/test-worker-imports.js +25 -0
- package/node_modules/ssh2/test/test.js +20 -0
- package/node_modules/ssh2/util/build_pagent.bat +2 -0
- package/node_modules/ssh2/util/pagent.c +88 -0
- package/node_modules/ssh2/util/pagent.exe +0 -0
- package/node_modules/tweetnacl/.npmignore +4 -0
- package/node_modules/tweetnacl/AUTHORS.md +28 -0
- package/node_modules/tweetnacl/CHANGELOG.md +221 -0
- package/node_modules/tweetnacl/LICENSE +24 -0
- package/node_modules/tweetnacl/PULL_REQUEST_TEMPLATE.md +20 -0
- package/node_modules/tweetnacl/README.md +459 -0
- package/node_modules/tweetnacl/nacl-fast.js +2388 -0
- package/node_modules/tweetnacl/nacl-fast.min.js +2 -0
- package/node_modules/tweetnacl/nacl.d.ts +98 -0
- package/node_modules/tweetnacl/nacl.js +1175 -0
- package/node_modules/tweetnacl/nacl.min.js +1 -0
- package/node_modules/tweetnacl/package.json +58 -0
- package/package.json +96 -89
package/lib/search.js
CHANGED
|
@@ -1,230 +1,235 @@
|
|
|
1
|
-
// dsh-remote — portable recursive search over SFTP.
|
|
2
|
-
// Replaces `find … -exec grep` (which needs a POSIX shell and dies on
|
|
3
|
-
// Windows remotes). Walks the remote tree over SFTP readdir/stat/readFile with
|
|
4
|
-
// the same bounded-parallelism + ignore rules as the mirror sync.
|
|
5
|
-
import { joinRemotePath, shq } from './paths.js'
|
|
6
|
-
|
|
7
|
-
function mapLimit(items, limit, fn) {
|
|
8
|
-
const limitN = Math.max(1, Math.min(Math.floor(limit) || 1, items.length))
|
|
9
|
-
let next = 0
|
|
10
|
-
const worker = async () => {
|
|
11
|
-
while (next < items.length) {
|
|
12
|
-
const i = next++
|
|
13
|
-
try { await fn(items[i], i) } catch { /* per-item errors are the fn's concern */ }
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
const workers = []
|
|
17
|
-
for (let w = 0; w < limitN; w++) workers.push(worker())
|
|
18
|
-
return Promise.all(workers)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/** fnmatch-lite for the `glob` filter (matches the entry BASENAME). */
|
|
22
|
-
export function matchGlob(name, glob) {
|
|
23
|
-
let re = ''
|
|
24
|
-
let i = 0
|
|
25
|
-
const g = String(glob || '')
|
|
26
|
-
while (i < g.length) {
|
|
27
|
-
const c = g[i]
|
|
28
|
-
if (c === '*') {
|
|
29
|
-
if (g[i + 1] === '*') { re += '.*'; i += 2; continue }
|
|
30
|
-
re += '[^/]*'; i++; continue
|
|
31
|
-
}
|
|
32
|
-
if (c === '?') { re += '[^/]'; i++; continue }
|
|
33
|
-
if ('\\^$+{}[]()|.'.includes(c)) re += '\\' + c
|
|
34
|
-
else re += c
|
|
35
|
-
i++
|
|
36
|
-
}
|
|
37
|
-
return new RegExp('^' + re + '$').test(String(name))
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const BINARY_SNIFF = 8192
|
|
41
|
-
function looksBinary(buf) {
|
|
42
|
-
const n = Math.min(buf.length, BINARY_SNIFF)
|
|
43
|
-
for (let i = 0; i < n; i++) if (buf[i] === 0) return true
|
|
44
|
-
return false
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Recursively search a remote directory.
|
|
49
|
-
*
|
|
50
|
-
* Cancellation (issue #44): the walk takes an AbortSignal and checks it at every
|
|
51
|
-
* directory and every entry. Before this it was completely uninterruptible —
|
|
52
|
-
* no signal was accepted and no flag was consulted — so a large-tree search
|
|
53
|
-
* could never be stopped: DSH tool cancellation is *cooperative*
|
|
54
|
-
* (@deepseek-ai/dsh-tool-call-timeout-policy can only ask a tool to stop), which
|
|
55
|
-
* meant `session/cancel`, steering, and the tool timeout policy all had no
|
|
56
|
-
* effect and the turn stayed `running` forever. On abort we return the partial
|
|
57
|
-
* result instead of throwing, so the model still gets whatever was found.
|
|
58
|
-
*
|
|
59
|
-
* @param {object} sftp - pooled SFTP client
|
|
60
|
-
* @param {string} rootDir
|
|
61
|
-
* @param {object} opts - `signal` (AbortSignal), `maxDurationMs`, plus the caps below
|
|
62
|
-
* @returns {Promise<{matches: Array<{path, line, text}>, scanned: number, truncated: boolean, cancelled?: boolean}>}
|
|
63
|
-
*/
|
|
64
|
-
export async function searchTree(sftp, rootDir, opts = {}) {
|
|
65
|
-
const {
|
|
66
|
-
regex, // RegExp (already compiled with ignoreCase where asked)
|
|
67
|
-
glob, // optional basename glob filter
|
|
68
|
-
contextLines = 0,
|
|
69
|
-
maxMatches = 500,
|
|
70
|
-
maxDepth = 12,
|
|
71
|
-
maxFiles = 20000,
|
|
72
|
-
maxScanBytes = 1024 * 1024,
|
|
73
|
-
maxDurationMs = 0, // 0 = no wall-clock budget
|
|
74
|
-
isIgnored = () => false,
|
|
75
|
-
signal,
|
|
76
|
-
} = opts
|
|
77
|
-
|
|
78
|
-
const matches = []
|
|
79
|
-
let scanned = 0
|
|
80
|
-
let truncated = false
|
|
81
|
-
let cancelled = false
|
|
82
|
-
const startedAt = Date.now()
|
|
83
|
-
|
|
84
|
-
/** True when the caller asked us to stop (abort, or the time budget is spent). */
|
|
85
|
-
const shouldStop = () => {
|
|
86
|
-
if (cancelled || truncated) return true
|
|
87
|
-
if (signal && signal.aborted) { cancelled = true; return true }
|
|
88
|
-
if (maxDurationMs > 0 && Date.now() - startedAt >= maxDurationMs) { truncated = true; return true }
|
|
89
|
-
return false
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const walk = async (dir, depth) => {
|
|
93
|
-
if (shouldStop() || scanned >= maxFiles) return
|
|
94
|
-
let entries = []
|
|
95
|
-
try { entries = (await sftp.readdir(dir)) || [] } catch { return }
|
|
96
|
-
const dirs = []
|
|
97
|
-
for (const e of entries) {
|
|
98
|
-
const name = String(e.filename)
|
|
99
|
-
if (name === '.' || name === '..') continue
|
|
100
|
-
const isDir = !!(e.attrs && e.attrs.isDirectory && e.attrs.isDirectory())
|
|
101
|
-
if (isDir) dirs.push(name)
|
|
102
|
-
}
|
|
103
|
-
// Depth-first, dirs first, but stop as soon as we hit caps.
|
|
104
|
-
for (const name of dirs) {
|
|
105
|
-
if (shouldStop() || scanned >= maxFiles) return
|
|
106
|
-
if (depth <= 0) continue
|
|
107
|
-
const sub = joinRemotePath(dir, name)
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if (
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if (
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (matches.length >= maxMatches) { truncated = true; return }
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
const
|
|
194
|
-
const
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
if
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
//
|
|
204
|
-
if (res.signal === '
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
1
|
+
// dsh-remote — portable recursive search over SFTP.
|
|
2
|
+
// Replaces `find … -exec grep` (which needs a POSIX shell and dies on
|
|
3
|
+
// Windows remotes). Walks the remote tree over SFTP readdir/stat/readFile with
|
|
4
|
+
// the same bounded-parallelism + ignore rules as the mirror sync.
|
|
5
|
+
import { joinRemotePath, relPathUnder, shq } from './paths.js'
|
|
6
|
+
|
|
7
|
+
function mapLimit(items, limit, fn) {
|
|
8
|
+
const limitN = Math.max(1, Math.min(Math.floor(limit) || 1, items.length))
|
|
9
|
+
let next = 0
|
|
10
|
+
const worker = async () => {
|
|
11
|
+
while (next < items.length) {
|
|
12
|
+
const i = next++
|
|
13
|
+
try { await fn(items[i], i) } catch { /* per-item errors are the fn's concern */ }
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
const workers = []
|
|
17
|
+
for (let w = 0; w < limitN; w++) workers.push(worker())
|
|
18
|
+
return Promise.all(workers)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** fnmatch-lite for the `glob` filter (matches the entry BASENAME). */
|
|
22
|
+
export function matchGlob(name, glob) {
|
|
23
|
+
let re = ''
|
|
24
|
+
let i = 0
|
|
25
|
+
const g = String(glob || '')
|
|
26
|
+
while (i < g.length) {
|
|
27
|
+
const c = g[i]
|
|
28
|
+
if (c === '*') {
|
|
29
|
+
if (g[i + 1] === '*') { re += '.*'; i += 2; continue }
|
|
30
|
+
re += '[^/]*'; i++; continue
|
|
31
|
+
}
|
|
32
|
+
if (c === '?') { re += '[^/]'; i++; continue }
|
|
33
|
+
if ('\\^$+{}[]()|.'.includes(c)) re += '\\' + c
|
|
34
|
+
else re += c
|
|
35
|
+
i++
|
|
36
|
+
}
|
|
37
|
+
return new RegExp('^' + re + '$').test(String(name))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const BINARY_SNIFF = 8192
|
|
41
|
+
function looksBinary(buf) {
|
|
42
|
+
const n = Math.min(buf.length, BINARY_SNIFF)
|
|
43
|
+
for (let i = 0; i < n; i++) if (buf[i] === 0) return true
|
|
44
|
+
return false
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Recursively search a remote directory.
|
|
49
|
+
*
|
|
50
|
+
* Cancellation (issue #44): the walk takes an AbortSignal and checks it at every
|
|
51
|
+
* directory and every entry. Before this it was completely uninterruptible —
|
|
52
|
+
* no signal was accepted and no flag was consulted — so a large-tree search
|
|
53
|
+
* could never be stopped: DSH tool cancellation is *cooperative*
|
|
54
|
+
* (@deepseek-ai/dsh-tool-call-timeout-policy can only ask a tool to stop), which
|
|
55
|
+
* meant `session/cancel`, steering, and the tool timeout policy all had no
|
|
56
|
+
* effect and the turn stayed `running` forever. On abort we return the partial
|
|
57
|
+
* result instead of throwing, so the model still gets whatever was found.
|
|
58
|
+
*
|
|
59
|
+
* @param {object} sftp - pooled SFTP client
|
|
60
|
+
* @param {string} rootDir
|
|
61
|
+
* @param {object} opts - `signal` (AbortSignal), `maxDurationMs`, plus the caps below
|
|
62
|
+
* @returns {Promise<{matches: Array<{path, line, text}>, scanned: number, truncated: boolean, cancelled?: boolean}>}
|
|
63
|
+
*/
|
|
64
|
+
export async function searchTree(sftp, rootDir, opts = {}) {
|
|
65
|
+
const {
|
|
66
|
+
regex, // RegExp (already compiled with ignoreCase where asked)
|
|
67
|
+
glob, // optional basename glob filter
|
|
68
|
+
contextLines = 0,
|
|
69
|
+
maxMatches = 500,
|
|
70
|
+
maxDepth = 12,
|
|
71
|
+
maxFiles = 20000,
|
|
72
|
+
maxScanBytes = 1024 * 1024,
|
|
73
|
+
maxDurationMs = 0, // 0 = no wall-clock budget
|
|
74
|
+
isIgnored = () => false,
|
|
75
|
+
signal,
|
|
76
|
+
} = opts
|
|
77
|
+
|
|
78
|
+
const matches = []
|
|
79
|
+
let scanned = 0
|
|
80
|
+
let truncated = false
|
|
81
|
+
let cancelled = false
|
|
82
|
+
const startedAt = Date.now()
|
|
83
|
+
|
|
84
|
+
/** True when the caller asked us to stop (abort, or the time budget is spent). */
|
|
85
|
+
const shouldStop = () => {
|
|
86
|
+
if (cancelled || truncated) return true
|
|
87
|
+
if (signal && signal.aborted) { cancelled = true; return true }
|
|
88
|
+
if (maxDurationMs > 0 && Date.now() - startedAt >= maxDurationMs) { truncated = true; return true }
|
|
89
|
+
return false
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const walk = async (dir, depth) => {
|
|
93
|
+
if (shouldStop() || scanned >= maxFiles) return
|
|
94
|
+
let entries = []
|
|
95
|
+
try { entries = (await sftp.readdir(dir)) || [] } catch { return }
|
|
96
|
+
const dirs = []
|
|
97
|
+
for (const e of entries) {
|
|
98
|
+
const name = String(e.filename)
|
|
99
|
+
if (name === '.' || name === '..') continue
|
|
100
|
+
const isDir = !!(e.attrs && e.attrs.isDirectory && e.attrs.isDirectory())
|
|
101
|
+
if (isDir) dirs.push(name)
|
|
102
|
+
}
|
|
103
|
+
// Depth-first, dirs first, but stop as soon as we hit caps.
|
|
104
|
+
for (const name of dirs) {
|
|
105
|
+
if (shouldStop() || scanned >= maxFiles) return
|
|
106
|
+
if (depth <= 0) continue
|
|
107
|
+
const sub = joinRemotePath(dir, name)
|
|
108
|
+
// isIgnored receives the path RELATIVE to the search root (the same
|
|
109
|
+
// contract sync has), so root-anchored ignore rules — `/proc/` when the
|
|
110
|
+
// workspace is the filesystem root (issue #60), `Library/Caches/` in the
|
|
111
|
+
// default search set — actually match here; a bare basename would never
|
|
112
|
+
// satisfy an anchored pattern and those rules were silently dead.
|
|
113
|
+
if (isIgnored(relPathUnder(rootDir, sub) || name, true)) continue
|
|
114
|
+
await walk(sub, depth - 1)
|
|
115
|
+
}
|
|
116
|
+
if (shouldStop() || scanned >= maxFiles) return
|
|
117
|
+
|
|
118
|
+
const fileNames = entries
|
|
119
|
+
.filter((e) => !(e.attrs && e.attrs.isDirectory && e.attrs.isDirectory()))
|
|
120
|
+
.map((e) => String(e.filename))
|
|
121
|
+
.filter((n) => n !== '.' && n !== '..')
|
|
122
|
+
await mapLimit(fileNames, 4, async (name) => {
|
|
123
|
+
// Checked per entry: this is the loop that used to run for hours.
|
|
124
|
+
if (shouldStop() || scanned >= maxFiles || matches.length >= maxMatches) return
|
|
125
|
+
if (glob && !matchGlob(name, glob)) return
|
|
126
|
+
const fp = joinRemotePath(dir, name)
|
|
127
|
+
if (isIgnored(relPathUnder(rootDir, fp) || name, false)) return
|
|
128
|
+
scanned++
|
|
129
|
+
let st
|
|
130
|
+
try { st = await sftp.stat(fp) } catch { return }
|
|
131
|
+
if (shouldStop()) return
|
|
132
|
+
if (st.size > maxScanBytes) return
|
|
133
|
+
let buf
|
|
134
|
+
try { buf = await sftp.readFile(fp) } catch { return }
|
|
135
|
+
if (shouldStop()) return
|
|
136
|
+
if (looksBinary(buf)) return
|
|
137
|
+
const content = buf.toString('utf8').replace(/\r\n/g, '\n')
|
|
138
|
+
const lines = content.split('\n')
|
|
139
|
+
const hitLines = new Set()
|
|
140
|
+
for (let i = 0; i < lines.length; i++) {
|
|
141
|
+
if (regex.test(lines[i])) {
|
|
142
|
+
regex.lastIndex = 0
|
|
143
|
+
for (let c = Math.max(0, i - contextLines); c <= Math.min(lines.length - 1, i + contextLines); c++) {
|
|
144
|
+
hitLines.add(c)
|
|
145
|
+
}
|
|
146
|
+
if (matches.length >= maxMatches) { truncated = true; return }
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (hitLines.size) {
|
|
150
|
+
for (const ln of [...hitLines].sort((a, b) => a - b)) {
|
|
151
|
+
if (matches.length >= maxMatches) { truncated = true; return }
|
|
152
|
+
matches.push({ path: fp, line: ln + 1, text: lines[ln] })
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
})
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
await walk(rootDir, maxDepth)
|
|
159
|
+
if (scanned >= maxFiles) truncated = true
|
|
160
|
+
return { matches, scanned, truncated, cancelled }
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function parseGrepLines(stdout, maxMatches) {
|
|
164
|
+
const matches = []
|
|
165
|
+
let truncated = false
|
|
166
|
+
for (const line of String(stdout || '').split('\n')) {
|
|
167
|
+
if (!line) continue
|
|
168
|
+
const m = line.match(/^(.*?):(\d+):(.*)$/)
|
|
169
|
+
if (!m) continue
|
|
170
|
+
if (matches.length >= maxMatches) { truncated = true; break }
|
|
171
|
+
matches.push({ path: m[1], line: Number(m[2]), text: m[3] })
|
|
172
|
+
}
|
|
173
|
+
return { matches, truncated }
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* POSIX fast path: `rg` then `grep -R`. Returns null when the remote has
|
|
178
|
+
* neither, so the caller can fall back to an SFTP walk (Windows / no grep).
|
|
179
|
+
*/
|
|
180
|
+
export async function searchViaShell(pool, rootDir, opts = {}) {
|
|
181
|
+
const {
|
|
182
|
+
pattern,
|
|
183
|
+
ignoreCase = true,
|
|
184
|
+
glob,
|
|
185
|
+
contextLines = 0,
|
|
186
|
+
maxMatches = 500,
|
|
187
|
+
signal,
|
|
188
|
+
} = opts
|
|
189
|
+
// Honour an already-aborted signal before spawning a remote grep on a huge tree.
|
|
190
|
+
if (signal && signal.aborted) {
|
|
191
|
+
return { matches: [], scanned: 0, truncated: false, cancelled: true, via: 'none' }
|
|
192
|
+
}
|
|
193
|
+
const ic = ignoreCase ? ' -i' : ''
|
|
194
|
+
const globFlag = glob ? ` --glob ${shq(glob)}` : ''
|
|
195
|
+
const ctx = contextLines > 0 ? ` -C ${Number(contextLines)}` : ''
|
|
196
|
+
const rg = `rg -n --no-heading -I${ic}${globFlag}${ctx} --max-count ${maxMatches} -- ${shq(pattern)} ${shq(rootDir)}`
|
|
197
|
+
const grepGlob = glob ? ` --include=${shq(glob)}` : ''
|
|
198
|
+
const grep = `grep -R -n -I -E${ic}${grepGlob}${ctx} -- ${shq(pattern)} ${shq(rootDir)}`
|
|
199
|
+
const script = `if command -v rg >/dev/null 2>&1; then ${rg}; elif command -v grep >/dev/null 2>&1; then ${grep}; else exit 127; fi`
|
|
200
|
+
const res = await pool.exec(script, { timeoutMs: opts.timeoutMs, signal })
|
|
201
|
+
// A cancelled call must return as cancelled (with whatever partial output the
|
|
202
|
+
// remote produced), NOT throw: throwing would make searchRemote fall through
|
|
203
|
+
// to the slower SFTP walk, i.e. keep running after the caller said stop.
|
|
204
|
+
if (res.signal === 'ABORTED') {
|
|
205
|
+
const partial = parseGrepLines(res.stdout, maxMatches)
|
|
206
|
+
return { matches: partial.matches, scanned: partial.matches.length, truncated: false, cancelled: true, via: 'none' }
|
|
207
|
+
}
|
|
208
|
+
// 0 = hits, 1 = no hits; other codes mean the tools are missing / failed.
|
|
209
|
+
if (res.signal === 'TIMEOUT') throw new Error('search timed out')
|
|
210
|
+
if (res.code !== 0 && res.code !== 1) throw new Error(res.stderr || `search exit ${res.code}`)
|
|
211
|
+
const parsed = parseGrepLines(res.stdout, maxMatches)
|
|
212
|
+
return {
|
|
213
|
+
matches: parsed.matches,
|
|
214
|
+
scanned: parsed.matches.length,
|
|
215
|
+
truncated: parsed.truncated || /truncated|max-count/i.test(String(res.stderr || '')),
|
|
216
|
+
via: /rg/.test(String(res.stderr || '')) ? 'rg' : 'grep',
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/** Prefer a POSIX grep/rg, fall back to the portable SFTP walk. */
|
|
221
|
+
export async function searchRemote(pool, rootDir, opts = {}) {
|
|
222
|
+
if (pool && pool.platform !== 'windows') {
|
|
223
|
+
try {
|
|
224
|
+
const fast = await searchViaShell(pool, rootDir, opts)
|
|
225
|
+
if (fast && Array.isArray(fast.matches)) return fast
|
|
226
|
+
} catch (e) {
|
|
227
|
+
// An abort is terminal, not a "try the slower fallback" signal.
|
|
228
|
+
if (opts.signal && opts.signal.aborted) {
|
|
229
|
+
return { matches: [], scanned: 0, truncated: false, cancelled: true, via: 'none' }
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
const sftp = await pool.sftp()
|
|
234
|
+
return searchTree(sftp, rootDir, opts)
|
|
235
|
+
}
|
package/lib/sftp-surface.js
CHANGED
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
// dsh-remote — the promisified SFTP surface every backend presents.
|
|
2
|
-
//
|
|
3
|
-
// Both SSH transports (the native ssh2 pool in lib/pool.js and the
|
|
4
|
-
// system-OpenSSH pool in lib/openssh.js) must expose the SAME object to
|
|
5
|
-
// callers: lib/sync.js, lib/search.js, lib/routes-fs.js, lib/remote-fs.js and
|
|
6
|
-
// the rw_* tools all consume this exact shape. Keeping one implementation
|
|
7
|
-
// matters more than it looks: the timeout, dead-channel and range-read rules
|
|
8
|
-
// below encode failures that were expensive to find (issue #44), and a second
|
|
9
|
-
// hand-copied version would drift away from the fixed one.
|
|
10
|
-
//
|
|
11
|
-
// The two rules that are easy to get wrong:
|
|
12
|
-
// • A dead channel must fail FAST. ssh2's own EOF handling only rejects the
|
|
13
|
-
// requests pending at that moment; every later request is registered and
|
|
14
|
-
// never answered, so each waits out the full commandTimeoutMs. Over a tree
|
|
15
|
-
// walk that is N × 2 × timeout — days on a large directory.
|
|
16
|
-
// • `readPartial` exists so an oversized preview never downloads the whole
|
|
17
|
-
// file to show its head.
|
|
18
|
-
import { toSftpPath } from './paths.js'
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Wrap a live SFTP channel (ssh2's SFTP instance) in the promisified surface
|
|
22
|
-
* the plugin's callers expect.
|
|
23
|
-
*
|
|
24
|
-
* @param {object} sftp - an ssh2 SFTP channel (already negotiated/ready).
|
|
25
|
-
* @param {object} opts
|
|
26
|
-
* @param {number} opts.commandTimeoutMs - per-operation timeout.
|
|
27
|
-
* @returns {object} promisified sftp surface.
|
|
28
|
-
*/
|
|
29
|
-
export function buildSftpSurface(sftp, { commandTimeoutMs }) {
|
|
30
|
-
// A dead channel must fail fast (see the header). ssh2's SFTP instance and the
|
|
31
|
-
// system-OpenSSH engine both emit these, so one hook covers both backends.
|
|
32
|
-
let dead = false
|
|
33
|
-
const markDead = () => { dead = true }
|
|
34
|
-
if (typeof sftp.on === 'function') {
|
|
35
|
-
sftp.on('end', markDead)
|
|
36
|
-
sftp.on('close', markDead)
|
|
37
|
-
sftp.on('error', markDead)
|
|
38
|
-
}
|
|
39
|
-
const withTimeout = (fn) => (...args) =>
|
|
40
|
-
new Promise((resolve, reject) => {
|
|
41
|
-
if (dead) return reject(new Error('sftp channel closed'))
|
|
42
|
-
const timer = setTimeout(() => reject(new Error('sftp operation timed out')), commandTimeoutMs)
|
|
43
|
-
const finish = (err, value) => {
|
|
44
|
-
clearTimeout(timer)
|
|
45
|
-
err ? reject(err) : resolve(value)
|
|
46
|
-
}
|
|
47
|
-
try { fn(...args, finish) } catch (err) { clearTimeout(timer); reject(err) }
|
|
48
|
-
})
|
|
49
|
-
const P = (p) => toSftpPath(p)
|
|
50
|
-
return {
|
|
51
|
-
readdir: (dir) => withTimeout((d, cb) => sftp.readdir(d, cb))(P(dir)),
|
|
52
|
-
stat: (p) => withTimeout((d, cb) => sftp.stat(d, cb))(P(p)),
|
|
53
|
-
lstat: (p) => withTimeout((d, cb) => sftp.lstat(d, cb))(P(p)),
|
|
54
|
-
mkdir: (dir) => withTimeout((d, cb) => sftp.mkdir(d, cb))(P(dir)),
|
|
55
|
-
rmdir: (dir) => withTimeout((d, cb) => sftp.rmdir(d, cb))(P(dir)),
|
|
56
|
-
unlink: (p) => withTimeout((d, cb) => sftp.unlink(d, cb))(P(p)),
|
|
57
|
-
rename: (p, d) => withTimeout((a, b, cb) => sftp.rename(a, b, cb))(P(p), P(d)),
|
|
58
|
-
realpath: (p) => withTimeout((d, cb) => sftp.realpath(d, cb))(P(p)),
|
|
59
|
-
readFile: (p) => withTimeout((d, cb) => sftp.readFile(d, cb))(P(p)),
|
|
60
|
-
writeFile: (p, data) => withTimeout((d, data2, cb) => sftp.writeFile(d, data2, cb))(P(p), data),
|
|
61
|
-
fastGet: (p, lp) => withTimeout((d, l, cb) => sftp.fastGet(d, l, cb))(P(p), lp),
|
|
62
|
-
fastPut: (lp, p) => withTimeout((l, d, cb) => sftp.fastPut(l, d, cb))(lp, P(p)),
|
|
63
|
-
// Range read for oversized previews: never downloads the whole file.
|
|
64
|
-
readPartial: (p, offset, length) => withTimeout((d, off, len, cb) => {
|
|
65
|
-
sftp.open(d, 'r', (e, handle) => {
|
|
66
|
-
if (e) return cb(e)
|
|
67
|
-
const buf = Buffer.alloc(len)
|
|
68
|
-
sftp.read(handle, buf, 0, len, off, (e2, bytesRead, data) => {
|
|
69
|
-
sftp.close(handle, () => {})
|
|
70
|
-
if (e2) return cb(e2)
|
|
71
|
-
cb(null, Buffer.isBuffer(data) ? data.subarray(0, bytesRead) : buf.subarray(0, bytesRead))
|
|
72
|
-
})
|
|
73
|
-
})
|
|
74
|
-
})(P(p), offset, length),
|
|
75
|
-
}
|
|
76
|
-
}
|
|
1
|
+
// dsh-remote — the promisified SFTP surface every backend presents.
|
|
2
|
+
//
|
|
3
|
+
// Both SSH transports (the native ssh2 pool in lib/pool.js and the
|
|
4
|
+
// system-OpenSSH pool in lib/openssh.js) must expose the SAME object to
|
|
5
|
+
// callers: lib/sync.js, lib/search.js, lib/routes-fs.js, lib/remote-fs.js and
|
|
6
|
+
// the rw_* tools all consume this exact shape. Keeping one implementation
|
|
7
|
+
// matters more than it looks: the timeout, dead-channel and range-read rules
|
|
8
|
+
// below encode failures that were expensive to find (issue #44), and a second
|
|
9
|
+
// hand-copied version would drift away from the fixed one.
|
|
10
|
+
//
|
|
11
|
+
// The two rules that are easy to get wrong:
|
|
12
|
+
// • A dead channel must fail FAST. ssh2's own EOF handling only rejects the
|
|
13
|
+
// requests pending at that moment; every later request is registered and
|
|
14
|
+
// never answered, so each waits out the full commandTimeoutMs. Over a tree
|
|
15
|
+
// walk that is N × 2 × timeout — days on a large directory.
|
|
16
|
+
// • `readPartial` exists so an oversized preview never downloads the whole
|
|
17
|
+
// file to show its head.
|
|
18
|
+
import { toSftpPath } from './paths.js'
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Wrap a live SFTP channel (ssh2's SFTP instance) in the promisified surface
|
|
22
|
+
* the plugin's callers expect.
|
|
23
|
+
*
|
|
24
|
+
* @param {object} sftp - an ssh2 SFTP channel (already negotiated/ready).
|
|
25
|
+
* @param {object} opts
|
|
26
|
+
* @param {number} opts.commandTimeoutMs - per-operation timeout.
|
|
27
|
+
* @returns {object} promisified sftp surface.
|
|
28
|
+
*/
|
|
29
|
+
export function buildSftpSurface(sftp, { commandTimeoutMs }) {
|
|
30
|
+
// A dead channel must fail fast (see the header). ssh2's SFTP instance and the
|
|
31
|
+
// system-OpenSSH engine both emit these, so one hook covers both backends.
|
|
32
|
+
let dead = false
|
|
33
|
+
const markDead = () => { dead = true }
|
|
34
|
+
if (typeof sftp.on === 'function') {
|
|
35
|
+
sftp.on('end', markDead)
|
|
36
|
+
sftp.on('close', markDead)
|
|
37
|
+
sftp.on('error', markDead)
|
|
38
|
+
}
|
|
39
|
+
const withTimeout = (fn) => (...args) =>
|
|
40
|
+
new Promise((resolve, reject) => {
|
|
41
|
+
if (dead) return reject(new Error('sftp channel closed'))
|
|
42
|
+
const timer = setTimeout(() => reject(new Error('sftp operation timed out')), commandTimeoutMs)
|
|
43
|
+
const finish = (err, value) => {
|
|
44
|
+
clearTimeout(timer)
|
|
45
|
+
err ? reject(err) : resolve(value)
|
|
46
|
+
}
|
|
47
|
+
try { fn(...args, finish) } catch (err) { clearTimeout(timer); reject(err) }
|
|
48
|
+
})
|
|
49
|
+
const P = (p) => toSftpPath(p)
|
|
50
|
+
return {
|
|
51
|
+
readdir: (dir) => withTimeout((d, cb) => sftp.readdir(d, cb))(P(dir)),
|
|
52
|
+
stat: (p) => withTimeout((d, cb) => sftp.stat(d, cb))(P(p)),
|
|
53
|
+
lstat: (p) => withTimeout((d, cb) => sftp.lstat(d, cb))(P(p)),
|
|
54
|
+
mkdir: (dir) => withTimeout((d, cb) => sftp.mkdir(d, cb))(P(dir)),
|
|
55
|
+
rmdir: (dir) => withTimeout((d, cb) => sftp.rmdir(d, cb))(P(dir)),
|
|
56
|
+
unlink: (p) => withTimeout((d, cb) => sftp.unlink(d, cb))(P(p)),
|
|
57
|
+
rename: (p, d) => withTimeout((a, b, cb) => sftp.rename(a, b, cb))(P(p), P(d)),
|
|
58
|
+
realpath: (p) => withTimeout((d, cb) => sftp.realpath(d, cb))(P(p)),
|
|
59
|
+
readFile: (p) => withTimeout((d, cb) => sftp.readFile(d, cb))(P(p)),
|
|
60
|
+
writeFile: (p, data) => withTimeout((d, data2, cb) => sftp.writeFile(d, data2, cb))(P(p), data),
|
|
61
|
+
fastGet: (p, lp) => withTimeout((d, l, cb) => sftp.fastGet(d, l, cb))(P(p), lp),
|
|
62
|
+
fastPut: (lp, p) => withTimeout((l, d, cb) => sftp.fastPut(l, d, cb))(lp, P(p)),
|
|
63
|
+
// Range read for oversized previews: never downloads the whole file.
|
|
64
|
+
readPartial: (p, offset, length) => withTimeout((d, off, len, cb) => {
|
|
65
|
+
sftp.open(d, 'r', (e, handle) => {
|
|
66
|
+
if (e) return cb(e)
|
|
67
|
+
const buf = Buffer.alloc(len)
|
|
68
|
+
sftp.read(handle, buf, 0, len, off, (e2, bytesRead, data) => {
|
|
69
|
+
sftp.close(handle, () => {})
|
|
70
|
+
if (e2) return cb(e2)
|
|
71
|
+
cb(null, Buffer.isBuffer(data) ? data.subarray(0, bytesRead) : buf.subarray(0, bytesRead))
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
})(P(p), offset, length),
|
|
75
|
+
}
|
|
76
|
+
}
|