diff --git a/.github/issue_template.md b/.github/issue_template.md index b396dbc73f..60318f794c 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -9,5 +9,5 @@ node -v npm -v # (or yarn -v) node -e "console.log(process.platform)" node -e "console.log(require('os').release())" -node -e "console.log(console.log(process.arch))" +node -e "console.log(process.arch)" ``` diff --git a/.github/workflows/build-openssl-packages.yml b/.github/workflows/build-openssl-packages.yml index bd584002d1..7b7a5dea3e 100644 --- a/.github/workflows/build-openssl-packages.yml +++ b/.github/workflows/build-openssl-packages.yml @@ -10,14 +10,14 @@ jobs: strategy: matrix: include: + - os: windows-latest + arch: arm64 - os: windows-latest arch: x64 - # - os: windows-latest - # arch: arm64 - os: macos-15 - arch: x64 - - os: macos-15-intel arch: arm64 + - os: macos-15-intel + arch: x64 fail-fast: false steps: @@ -29,28 +29,19 @@ jobs: with: node-version: 22 - - name: Install Toolchain - if: matrix.os == 'windows-latest' && matrix.arch == 'arm64' - uses: msys2/setup-msys2@v2 - with: - update: true - install: > - mingw-w64-aarch64-toolchain - mingw-w64-aarch64-cmake - mingw-w64-aarch64-ninja - - name: Install dependencies run: npm install - name: Build OpenSSL packages env: - TARGET_ARCH: ${{ matrix.arch }} + npm_config_arch: ${{ matrix.arch }} NODEGIT_OPENSSL_BUILD_PACKAGE: 1 OPENSSL_MACOS_DEPLOYMENT_TARGET: "11.0" run: node utils/acquireOpenSSL.mjs - name: Push OpenSSL package to S3 env: + npm_config_arch: ${{ matrix.arch }} node_pre_gyp_bucket: ${{ secrets.node_pre_gyp_bucket }} AWS_ACCESS_KEY_ID: ${{ secrets.node_pre_gyp_accessKeyId }} AWS_SECRET_ACCESS_KEY: ${{ secrets.node_pre_gyp_secretAccessKey }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3a2f8cc7ae..3cd6aae10c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -72,10 +72,9 @@ jobs: strategy: matrix: node: [20, 22, 24] + arch: [x64, arm64] fail-fast: false - runs-on: macOS-13 - # This is mostly the same as the Linux steps, waiting for anchor support - # https://github.com/actions/runner/issues/1182 + runs-on: ${{ matrix.arch == 'x64' && 'macos-15-intel' || 'macos-15' }} steps: - uses: actions/checkout@v4 @@ -123,7 +122,7 @@ jobs: strategy: matrix: node: [20, 22, 24] - arch: [x86, x64] + arch: [x86, x64, arm64] exclude: - node: 24 arch: x86 @@ -141,20 +140,36 @@ jobs: - uses: actions/checkout@v4 - name: Use Node.js + if: matrix.arch == 'x86' uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} check-latest: true - architecture: ${{ matrix.arch }} + architecture: x86 + + - name: Use Node.js + uses: actions/setup-node@v4 + if: matrix.arch != 'x86' + with: + node-version: ${{ matrix.node }} + check-latest: true - name: Install + env: + npm_config_arch: ${{ matrix.arch == 'x86' && 'ia32' || matrix.arch }} run: npm install - name: Test + # need arm64 runners or an emulator to run tests + if: matrix.arch != 'arm64' env: GIT_SSH: ${{ github.workspace }}\vendor\plink.exe run: | - powershell -command "Start-Process ${{ github.workspace }}\vendor\pageant.exe ${{ github.workspace }}\vendor\private.ppk" + $encodedKey = Get-Content -Path test\private.ppk.enc + $finalPath = Join-Path -Path $HOME -ChildPath .ssh_tests\private.ppk + mkdir ~\.ssh_tests + Set-Content -Value $([System.Convert]::FromBase64String($encodedKey)) -Path $finalPath -AsByteStream + powershell -command "Start-Process .\vendor\pageant\pageant_${{ matrix.arch }}.exe $finalPath" node utils/retry npm test # You're probably wondering why this isn't a single `run: |` step, it certainly is for *nix, @@ -170,7 +185,7 @@ jobs: - name: Deploy (Package) if: startsWith(github.ref, 'refs/tags/v') - run: node-pre-gyp package + run: node-pre-gyp package --target_arch=${{ matrix.arch }} - name: Deploy (Publish) if: startsWith(github.ref, 'refs/tags/v') @@ -178,4 +193,4 @@ jobs: node_pre_gyp_bucket: ${{ secrets.node_pre_gyp_bucket }} AWS_ACCESS_KEY_ID: ${{ secrets.node_pre_gyp_accessKeyId }} AWS_SECRET_ACCESS_KEY: ${{ secrets.node_pre_gyp_secretAccessKey }} - run: node-pre-gyp publish + run: node-pre-gyp publish --target_arch=${{ matrix.arch }} diff --git a/.gitignore b/.gitignore index feb22eaa22..7d1f15f049 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,4 @@ jsconfig.json test/id_rsa test/nodegit-test-rsa +test/private.ppk diff --git a/CHANGELOG.md b/CHANGELOG.md index 12d3a9dce0..d7c020aac7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,38 @@ # Change Log -## v0.28.0-alpha.34 [(2025-06-03)](https://github.com/nodegit/nodegit/releases/tag/v0.28.0-alpha.34) +## v0.28.0-alpha.36 [(2025-11-21)](https://github.com/nodegit/nodegit/releases/tag/v0.28.0-alpha.36) + +[Full Changelog](https://github.com/nodegit/nodegit/compare/v0.28.0-alpha.35...v0.28.0-alpha.36) + +#### Summary of Changes + - Use openssl unconditionally for linux electron builds + - Fix cross-compiling libssh2 + - Fix Windows SSH keys, tests, documentation + - Add CI tests and Prebuilts for MacOS arm64 + - Bump tar-fsa to fix security vulnerabilities + +#### Merged PRs into NodeGit +- [Bump tar-fs from 3.0.9 to 3.1.1](https://github.com/nodegit/nodegit/pull/2034) +- [Use custom electron for non-static builds on linux and fix cross-compilation](https://github.com/nodegit/nodegit/pull/2033) +- [add macos arm64 tests and prebuilts](https://github.com/nodegit/nodegit/pull/2030) + +## v0.28.0-alpha.35 [(2025-11-14)](https://github.com/nodegit/nodegit/releases/tag/v0.28.0-alpha.35) + +[Full Changelog](https://github.com/nodegit/nodegit/compare/v0.28.0-alpha.34...v0.28.0-alpha.35) + +#### Summary of Changes + - Bump libgit2 to 1.9.1 + - Bump OpenSSL to 3.0 + - Move OpenSSL Packaging to Github Actions + - Add arm64 build Support + +#### Merged PRs into NodeGit +- [Bump libgit2 to 1.9.1](https://github.com/nodegit/nodegit/pull/2025) +- [Bump OpenSSL to 3.0, Move OpenSSL package generation to Github Actions](https://github.com/nodegit/nodegit/pull/2026) +- [fix: correct macos arch labels](github.com/nodegit/nodegit/pull/2027) +- [Add Ability to compile for arm64](https://github.com/nodegit/nodegit/pull/2028) + +## v0.28.0-alpha.34 [(2025-07-23)](https://github.com/nodegit/nodegit/releases/tag/v0.28.0-alpha.34) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.28.0-alpha.33...v0.28.0-alpha.34) diff --git a/generate/input/descriptor.json b/generate/input/descriptor.json index 889b792e75..99837534db 100644 --- a/generate/input/descriptor.json +++ b/generate/input/descriptor.json @@ -1526,6 +1526,11 @@ } } }, + "email": { + "cDependencies": [ + "git2/sys/email.h" + ] + }, "email_create_options": { "hasConstructor": true }, diff --git a/generate/input/libgit2-supplement.json b/generate/input/libgit2-supplement.json index 09433e7fae..12ee8945b6 100644 --- a/generate/input/libgit2-supplement.json +++ b/generate/input/libgit2-supplement.json @@ -294,6 +294,54 @@ "isErrorCode": true } }, + "git_email_create_from_diff": { + "file": "sys/email.h", + "type": "function", + "isAsync": true, + "group": "email", + "args": [ + { + "name": "out", + "type": "git_buf *" + }, + { + "name": "diff", + "type": "git_diff *" + }, + { + "name": "patch_idx", + "type": "size_t" + }, + { + "name": "patch_count", + "type": "size_t" + }, + { + "name": "commit_id", + "type": "const git_oid *" + }, + { + "name": "summary", + "type": "const char *" + }, + { + "name": "body", + "type": "const char *" + }, + { + "name": "author", + "type": "const git_signature *" + }, + { + "name": "opts", + "type": "git_email_create_options *" + } + ], + "return": { + "type": "int", + "isErrorCode": true + } + }, "git_diff_get_perfdata": { "file": "sys/diff.h", "args": [ @@ -2396,12 +2444,6 @@ } } ], - [ - "git_time_t", - { - "type": "enum" - } - ], [ "git_trace_level_t", { @@ -2619,6 +2661,9 @@ "blame": [ "git_blame_file" ], + "email": [ + "git_email_create_from_diff" + ], "note": [ "git_note_author", "git_note_commit_create", diff --git a/generate/scripts/helpers.js b/generate/scripts/helpers.js index 15790983ff..e278e1cc05 100644 --- a/generate/scripts/helpers.js +++ b/generate/scripts/helpers.js @@ -25,7 +25,8 @@ var cTypeMappings = { "uint32_t": "Number", "uint64_t": "Number", "double": "Number", - "git_object_size_t": "Number" + "git_object_size_t": "Number", + "git_time_t": "Number", } var collisionMappings = { diff --git a/generate/templates/manual/include/configurable_class_wrapper.h b/generate/templates/manual/include/configurable_class_wrapper.h index 283eb7e44f..ff83a3176d 100644 --- a/generate/templates/manual/include/configurable_class_wrapper.h +++ b/generate/templates/manual/include/configurable_class_wrapper.h @@ -40,7 +40,7 @@ namespace nodegit { virtual ~ConfigurableClassWrapper() { if (raw != nullptr) { - delete raw; + free(raw); raw = nullptr; } } diff --git a/generate/templates/manual/repository/refresh_references.cc b/generate/templates/manual/repository/refresh_references.cc index 5ddaec57fa..5194f1c48c 100644 --- a/generate/templates/manual/repository/refresh_references.cc +++ b/generate/templates/manual/repository/refresh_references.cc @@ -244,10 +244,10 @@ class RefreshedRefModel { } ~RefreshedRefModel() { - if (fullName != NULL) { delete[] fullName; } - if (message != NULL) { delete[] message; } + if (fullName != NULL) { free(fullName); } + if (message != NULL) { free(message); } delete[] sha; - if (shorthand != NULL) { delete[] shorthand; } + if (shorthand != NULL) { free(shorthand); } if (tagOdbBuffer != NULL) { delete[] tagOdbBuffer; } } @@ -344,8 +344,8 @@ class UpstreamModel { } ~UpstreamModel() { - if (downstreamFullName != NULL) { delete[] downstreamFullName; } - if (upstreamFullName != NULL) { delete[] upstreamFullName; } + if (downstreamFullName != NULL) { free(downstreamFullName); } + if (upstreamFullName != NULL) { free(upstreamFullName); } } char *downstreamFullName; @@ -375,7 +375,7 @@ class RefreshReferencesData { delete upstreamInfo.back(); upstreamInfo.pop_back(); } - if (headRefFullName != NULL) { delete[] headRefFullName; } + if (headRefFullName != NULL) { free(headRefFullName); } if (cherrypick != NULL) { delete cherrypick; } if (merge != NULL) { delete merge; } } @@ -573,7 +573,7 @@ void GitRepository::RefreshReferencesWorker::Execute() if (isRemote) { char *remoteNameOfRef = getRemoteNameOfReference(reference); bool isFromExistingRemote = gitStrArrayContains(&remoteNames, remoteNameOfRef); - delete[] remoteNameOfRef; + free(remoteNameOfRef); if (!isFromExistingRemote) { git_reference_free(reference); continue; diff --git a/generate/templates/manual/revwalk/file_history_walk.cc b/generate/templates/manual/revwalk/file_history_walk.cc index 714d6f5db3..569bb022dc 100644 --- a/generate/templates/manual/revwalk/file_history_walk.cc +++ b/generate/templates/manual/revwalk/file_history_walk.cc @@ -31,6 +31,14 @@ class FileHistoryEvent { if (commit != NULL) { git_commit_free(commit); } + + if(from != NULL) { + free((void *)from); + } + + if(to != NULL) { + free((void *)to); + } } v8::Local toJavascript() { diff --git a/generate/templates/manual/src/str_array_converter.cc b/generate/templates/manual/src/str_array_converter.cc index 732f16cf26..5d04c65622 100644 --- a/generate/templates/manual/src/str_array_converter.cc +++ b/generate/templates/manual/src/str_array_converter.cc @@ -65,7 +65,7 @@ git_strarray *StrArrayConverter::ConstructStrArray(int argc, char** argv) { void StrArrayConverter::ConvertInto(git_strarray *out, v8::Local val) { out->count = val->Length(); - out->strings = new char *[out->count]; + out->strings = (char**) malloc(out->count * sizeof(char*)); for (uint32_t i = 0; i < out->count; ++i) { Nan::Utf8String utf8String(Nan::Get(val, i).ToLocalChecked().As()); out->strings[i] = strdup(*utf8String); @@ -75,6 +75,6 @@ void StrArrayConverter::ConvertInto(git_strarray *out, v8::Local val) void StrArrayConverter::ConvertInto(git_strarray *out, v8::Local val) { Nan::Utf8String utf8String(val); out->count = 1; - out->strings = new char *[1]; + out->strings = (char**) malloc(out->count * sizeof(char*)); out->strings[0] = strdup(*utf8String); } diff --git a/generate/templates/partials/async_function.cc b/generate/templates/partials/async_function.cc index a294043fab..d23ec7f609 100644 --- a/generate/templates/partials/async_function.cc +++ b/generate/templates/partials/async_function.cc @@ -56,7 +56,7 @@ NAN_METHOD({{ cppClassName }}::{{ cppFunctionName }}) { {% if arg.cppClassName == 'Array' %} { v8::Local tempArray = v8::Local::Cast(info[{{ arg.jsArg }}]); - baton->{{ arg.name }} = new {{ arg.cType|unPointer }}[tempArray->Length()]; + baton->{{ arg.name }} = ({{ arg.cType|unPointer }}*)malloc(sizeof({{ arg.cType|unPointer }}) * tempArray->Length()); for (uint32_t i = 0; i < tempArray->Length(); ++i) { auto conversionResult = Configurable{{ arg.arrayElementCppClassName }}::fromJavascript( nodegitContext, @@ -64,12 +64,13 @@ NAN_METHOD({{ cppClassName }}::{{ cppFunctionName }}) { ); if (!conversionResult.result) { - delete[] baton->{{ arg.name }}; + // TODO free previously allocated memory + free(baton->{{ arg.name }}); return Nan::ThrowError(Nan::New(conversionResult.error).ToLocalChecked()); } auto convertedObject = conversionResult.result; - cleanupHandles["{{ arg.name }}"] = convertedObject; + cleanupHandles[std::string("{{ arg.name }}") + std::to_string(i)] = convertedObject; baton->{{ arg.name }}[i] = *convertedObject->GetValue(); } } diff --git a/generate/templates/templates/binding.gyp b/generate/templates/templates/binding.gyp index b5e189c32c..4476c9236d 100644 --- a/generate/templates/templates/binding.gyp +++ b/generate/templates/templates/binding.gyp @@ -56,7 +56,7 @@ "include_dirs": [ "vendor/libv8-convert", "vendor/libssh2/include", - "(nodegitContext) { {% if ignoreInit == true %} - this->raw = new {{ cType }}; + this->raw = ({{ cType }}*) malloc(sizeof({{ cType }})); {% else %} {{ cType }}{% if isExtendedStruct %}_extended{% endif %} wrappedValue = {{ cType|upper }}_INIT; this->raw = ({{ cType }}*) malloc(sizeof({{ cType }}{% if isExtendedStruct %}_extended{% endif %})); @@ -132,12 +132,12 @@ Configurable{{ cppClassName }}::~Configurable{{ cppClassName }}() { {% if field.cppClassName == 'GitStrarray' %} if (this->raw->{{ field.name }}.count) { for (size_t i = 0; i < this->raw->{{ field.name }}.count; ++i) { - delete this->raw->{{ field.name }}.strings[i]; + free(this->raw->{{ field.name }}.strings[i]); } - delete[] this->raw->{{ field.name }}.strings; + free(this->raw->{{ field.name }}.strings); } {% elsif field.cppClassName == 'String' %} - delete this->raw->{{ field.name }}; + free((void*)this->raw->{{ field.name }}); {% endif %} {% endif %} {% endeach %} diff --git a/guides/install/from-source/README.md b/guides/install/from-source/README.md index eadd8306d8..64bfce18b3 100644 --- a/guides/install/from-source/README.md +++ b/guides/install/from-source/README.md @@ -65,7 +65,7 @@ npm install nodegit --msvs_version=2013 ``` ### Electron and OpenSSL ### -A local version of OpenSSL is required when building for Electron on Windows and macOS. This is due to Electron using BoringSSL, as we are not able to link to it like we are OpenSSL in Node. Additionally, OpenSSL can be statically linked on Linux by setting the `NODEGIT_OPENSSL_STATIC_LINK` environment variable to `1`. +A local version of OpenSSL is required when building for Electron. This is due to Electron using BoringSSL, as we are not able to link to it like we are OpenSSL in Node. `acquireOpenSSL.js` will attempt to download OpenSSL prebuilts from S3. If preferred, it can also be built locally by setting the environment variable `npm_config_openssl_bin_url=skip`. On macOS, this should Just Work(tm). On Windows, things are a little trickier. diff --git a/lib/credential.js b/lib/credential.js index db1f82a788..af1a59125e 100644 --- a/lib/credential.js +++ b/lib/credential.js @@ -16,6 +16,7 @@ NodeGit.Cred = { defaultNew: deprecatedFn("defaultNew"), sshKeyFromAgent: deprecatedFn("sshKeyFromAgent"), sshKeyNew: deprecatedFn("sshKeyNew"), + sshKeyMemoryNew: deprecatedFn("sshKeyMemoryNew"), usernameNew: deprecatedFn("usernameNew"), userpassPlaintextNew: deprecatedFn("userpassPlaintextNew"), TYPE: Object.keys(Credential.TYPE).reduce( diff --git a/lifecycleScripts/install.js b/lifecycleScripts/install.js index ddbb90e9c8..96e47afbe5 100755 --- a/lifecycleScripts/install.js +++ b/lifecycleScripts/install.js @@ -2,6 +2,8 @@ var buildFlags = require("../utils/buildFlags"); var spawn = require("child_process").spawn; var path = require("path"); +const nodePreGypModulePath = require.resolve("@mapbox/node-pre-gyp"); + module.exports = function install() { console.log("[nodegit] Running install script"); @@ -30,7 +32,10 @@ module.exports = function install() { return new Promise(function(resolve, reject) { const gypPath = path.join(__dirname, "..", "node_modules", "node-gyp", "bin", "node-gyp.js"); - var spawnedNodePreGyp = spawn(nodePreGyp, args, { + + const nodePreGypPath = path.resolve(path.dirname(nodePreGypModulePath), path.join("..", "bin", nodePreGyp)); + console.log("node-pre-gyp path", nodePreGypPath); + var spawnedNodePreGyp = spawn(nodePreGypPath, args, { env: { ...process.env, npm_config_node_gyp: gypPath diff --git a/package-lock.json b/package-lock.json index 25edeaf617..93f2f440d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,21 +1,21 @@ { "name": "nodegit", - "version": "0.28.0-alpha.34", + "version": "0.28.0-alpha.36", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "nodegit", - "version": "0.28.0-alpha.34", + "version": "0.28.0-alpha.36", "hasInstallScript": true, "license": "MIT", "dependencies": { - "@axosoft/nan": "^2.22.0-gk.1", "@mapbox/node-pre-gyp": "^2.0.0", "fs-extra": "^7.0.0", "got": "^14.4.7", "json5": "^2.1.0", "lodash": "^4.17.14", + "nan": "^2.23.1", "node-gyp": "^11.2.0", "tar-fs": "^3.0.9" }, @@ -48,12 +48,6 @@ "node": ">=6.0.0" } }, - "node_modules/@axosoft/nan": { - "version": "2.22.0-gk.1", - "resolved": "https://registry.npmjs.org/@axosoft/nan/-/nan-2.22.0-gk.1.tgz", - "integrity": "sha512-C4xrZ5HQoWwoq/WZnKDhf/Jd/czIaa0gsjHV792qUp7b7H+4Xtw1Um10BiiU/zrgmGhQuA92dedU2/rGvKErNg==", - "license": "MIT" - }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -85,6 +79,7 @@ "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -899,6 +894,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -1759,15 +1755,6 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -3985,6 +3972,12 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/nan": { + "version": "2.23.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.23.1.tgz", + "integrity": "sha512-r7bBUGKzlqk8oPBDYxt6Z0aEdF1G1rwlMcLk8LCOMbOzf0mG+JUfUzG4fIMWwHWP0iyaLWEQZJmtB7nOHEm/qw==", + "license": "MIT" + }, "node_modules/negotiator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", @@ -4522,6 +4515,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -5195,10 +5189,9 @@ } }, "node_modules/tar-fs": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.9.tgz", - "integrity": "sha512-XF4w9Xp+ZQgifKakjZYmFdkLoSWd34VGKcsTCwlNWM7QG3ZbaxnTsaBwnjFZqHRf/rROxaR8rXnbtwdvaDI+lA==", - "license": "MIT", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", + "integrity": "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==", "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" @@ -5969,11 +5962,6 @@ "@jridgewell/trace-mapping": "^0.3.24" } }, - "@axosoft/nan": { - "version": "2.22.0-gk.1", - "resolved": "https://registry.npmjs.org/@axosoft/nan/-/nan-2.22.0-gk.1.tgz", - "integrity": "sha512-C4xrZ5HQoWwoq/WZnKDhf/Jd/czIaa0gsjHV792qUp7b7H+4Xtw1Um10BiiU/zrgmGhQuA92dedU2/rGvKErNg==" - }, "@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -5996,6 +5984,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.7.tgz", "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==", "dev": true, + "peer": true, "requires": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -6545,6 +6534,7 @@ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "dev": true, + "peer": true, "requires": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -7198,15 +7188,6 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "optional": true, - "requires": { - "iconv-lite": "^0.6.2" - } - }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -7726,8 +7707,7 @@ } }, "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "optional": true, "requires": { @@ -8811,6 +8791,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "nan": { + "version": "2.23.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.23.1.tgz", + "integrity": "sha512-r7bBUGKzlqk8oPBDYxt6Z0aEdF1G1rwlMcLk8LCOMbOzf0mG+JUfUzG4fIMWwHWP0iyaLWEQZJmtB7nOHEm/qw==" + }, "negotiator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", @@ -9198,7 +9183,8 @@ "picomatch": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==" + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "peer": true }, "pkg-dir": { "version": "4.2.0", @@ -9686,9 +9672,9 @@ } }, "tar-fs": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.9.tgz", - "integrity": "sha512-XF4w9Xp+ZQgifKakjZYmFdkLoSWd34VGKcsTCwlNWM7QG3ZbaxnTsaBwnjFZqHRf/rROxaR8rXnbtwdvaDI+lA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", + "integrity": "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==", "requires": { "bare-fs": "^4.0.1", "bare-path": "^3.0.0", diff --git a/package.json b/package.json index fe1273285f..41ccc32dc4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "nodegit", "description": "Node.js libgit2 asynchronous native bindings", - "version": "0.28.0-alpha.34", + "version": "0.28.0-alpha.36", "homepage": "http://nodegit.org", "keywords": [ "libgit2", @@ -38,12 +38,12 @@ "node": ">= 20" }, "dependencies": { - "@axosoft/nan": "^2.22.0-gk.1", "@mapbox/node-pre-gyp": "^2.0.0", "fs-extra": "^7.0.0", "got": "^14.4.7", "json5": "^2.1.0", "lodash": "^4.17.14", + "nan": "^2.23.1", "node-gyp": "^11.2.0", "tar-fs": "^3.0.9" }, diff --git a/test/README.md b/test/README.md index e96c792177..e6bdccbc4d 100644 --- a/test/README.md +++ b/test/README.md @@ -17,5 +17,20 @@ Unit tests for NodeGit. Test utilities with garbage collector, index, and repository setup, that can be used in tests. -## Note -\*.enc are encrypted in base64 and unencrypted before the test suite runs as \*. +## Keys + +Note: all files are encoded in base64 in `\*.enc` and decoded before the test suite runs. + +### encrypted_rsa + - passphrase "test-password" + - registered as deploy key on [nodegit/test](https://github.com/nodegit/test) repo named "Encrypted test key" + +### id_rsa + - registered as deploy key on [nodegit/test](https://github.com/nodegit/test) repo named "Unencrypted Test Key" + +### private.ppk + - same key as id_rsa + - ppk format is used by putty/pageant and converted/generated by puttygen + +### nodegit-test-rsa + - registered as deploy key on [nodegit/private](https://github.com/nodegit/private) repo named "Tests" diff --git a/test/index.js b/test/index.js index b138525e15..abd2fc2174 100644 --- a/test/index.js +++ b/test/index.js @@ -40,6 +40,8 @@ function unencryptKey(fileName) { .toString('ascii'); fs.writeFileSync(path.join(__dirname, fileName), asciiContents, 'utf8'); } + +unencryptKey('private.ppk'); unencryptKey('id_rsa'); unencryptKey('nodegit-test-rsa'); diff --git a/test/private.ppk.enc b/test/private.ppk.enc new file mode 100644 index 0000000000..c388d98d86 --- /dev/null +++ b/test/private.ppk.enc @@ -0,0 +1,47 @@ +UHVUVFktVXNlci1LZXktRmlsZS0zOiBzc2gtcnNhCkVuY3J5cHRpb246IG5vbmUKQ29tbWVudDog +bm9uYW1lClB1YmxpYy1MaW5lczogMTIKQUFBQUIzTnphQzF5YzJFQUFBQURBUUFCQUFBQ0FRQ3dP +Y0VONis1Vkx2VXBQSGp3WnNiMHZIUEJBRzcxUmV5YwovQzAyMkhDWENJV05mOUwxSWduR25nSWU0 +OXdxdGUvWXFyYm5xMHVqOXlrSjE4Nm1GZHdoeUtBNUR2dm5SM1FmClQ5OG12VE94bnpDTUJ1QlU3 +M002UEpDYTZVekpoeXhtTjNVTU1uanEvU25oN3hycVdkYW1YQ2ROS3hRL0QxUlkKVXEzVGdLbnBI +bGxhSEI0dnoydHZvRXpBY0dzZ014aFZ4NWdoZ1YxT1Y1NzNYNFVDRXA1UVJNNHJ2WE9KMDRDLwpn +Mzl5KzFNQnladUpveno4OHBaUFg4UFVISGJOemFWd2JCeDFVRnVJdFVGeGo3WkRGK3hubDdTTDBl +RW0vc0dxClh3akhVenJlSmgwQXpZQUNYRVYwd3czZ0xSQ1pmSDEwa3RLMVlTcTFhQ0Vld1Z3MHNu +TUl3cjNSMkFjZkR5K0QKM1dhMXd0WGxNb3lDaTFhRUhwdmd1OFVOQWhteDdJVy9pcEdEZHcyaGQ0 +OVh1ZUh2MjVwaHI4S1ROdVRnWmdMNgpXYkVQckFSM3dieHp6QXJ5dmJEbWJ4N1RSbUNRQVJxZlA5 +MTlDQmF5MmwyUGgvNDFDNFJZV3pPeUxHS1F3bzFXCnRwbk9FVnBPRTRLYmRNK3g5dzBxQndEdTVa +TnRqcGd6WlBrbVBSSzhZU2NtUkRkSDRmNU1lT1dPd3Y3YTVoTUgKZHg2Q0JheGF3bUt1VFZLL2Q3 +VU9wRmRQRnhLbjJzU0l1RzZwWUlyOHJFTHF0ZU1EUnRVa2ZYUUtBWFl4NlJRVAphYmgvSlZ3ODB2 +OFJkaEs1YVRQTld3dlZ6RFpHek9VcTBjQkV2dmdjbG5PQzFqYnE4bEFyMzJlZzQvWXkyRWJpCjV2 +MkoydVBlNlE9PQpQcml2YXRlLUxpbmVzOiAyOApBQUFDQUYvalRSU1NKK0RaNkRSRDMxcVAwZm9o +QUtzbjNUaEFqL3Jyakg2blRyd2Z1dXUvZmI0OGd5MDdsTlBTCkVGNTlHTURBUXozVGl4and4N2Uv +WVlZbHB0NExHSU56ajhYTXIzYktNeFlWSlNlbEF2bHVWR3BpMEVRRDZIc2kKTHRJSlp6TkhRYjBk +U1lZenNySnBOREFJS2kvalBNOVVmWFBDbDVabmhvWHJJSWprSnFKTlltK0pZV0FmelNONQpDQkZC +UENDUXRrcWs1V3hYYVB3WlVYcExQekZWL3dqMTBRUlJ2V0IzNE1WajAwckp0SVF6K2w5NGNDbEla +bm5uCjh3MFF0TkJ6UXhqaVhLd0tWRTNDY040WkNsMWp3cTNCeWMwNkdZN21ueFEyU1hYUEwwRGNr +S2E0Sm1MZUw1S24KY3J6UmJFSWVFZUQzdWhGelUzSTByRU5RUmg2NjlJcHJhamZSekxjRnhuQzcz +QlMxUlR5Y2ZwZFNHRk9QWFQvMgpOZDM2MlhTZXA2Vk54U3Q1YTZ3a1dnSEpoMkg4ZFBjbmlESDFE +bXJBZFA5N0FrZWkxbG1YcWJ6Q0lWOXBpZDNtCmZNQUpiSm00UmhRcFREdmV1RThOaUJnSTYyVGt3 +dWNvVzJ5M0xkU3YxMzdpSkJuSlNjMTFHOUE1YkcyeVFYRTIKYWlYUXhIeW9UMlF0VmY1WklYUmFW +THViUW5jU2dMQmpnQ2QxQ2xqQjVqbFJZTXRTYzhiRmEvVEo1b1hPVk10QwpYNHhhcVo3Z3JHS05C +cUJsRFRXblRnWk1tdndQVnVjbGU3MjgzNk9KUFhvMUxqM0sza21yeEMxdU5HMDc2My96CmJLOWl2 +QWF1SFRMMnQ0cHkra0k0NC9ZcERvR2sybnhsV01kRDNMM0pVeDNRejlMeEFBQUJBUURiVG94anFO +UHIKRk9aYlg5M3g2TjU1SVdOQ1VLdXFMMVZLNjFESGFLWGZpaXdIRHlRYjEzUnhPREk2RlNXMElI +eVpqMDh5ZjBTVApJRjlzWU1BcDcvRktRTkRJalVWcjFSNmdERWdBdytjeS9naXlqMFVscUhNc2dU +UnNnSmEvSjJQYnViRDRWMzdZClJEOHpwdmtLZjhTSjBiUWpRMGlMdGFDVWJvQVA1ZmFhWGxJS3Zl +Mnh6S3VYM09Jdk0zTyt1UTBJMDZqZGtMc2IKQUcxL2dBOXpiZmltcEx3SUJCZFVJenY3aEUyajhi +aGpPR201U0lOa3M0WWVUTlRWV2R4ZnI3Yi8wVlFPSXJDdwpEUCsrQmhjOTdkK1g3WVVVZFFIM1Bw +U1dyVm9KTnNITXB1VFpoaXdDZ0ZNTU9UWEhHVmxqRThyZ2RlU2xQc2dCCjFzUWh4clJTTUIrZkFB +QUJBUUROdGU0KzFubFlLVjZFUVl4cnlKVUFLT3RNS0pmQTVYUlRzc1hoc0V5UjAwcS8KV2N3dHJm +ZjM1dzdmQVhCVndlTnplZWl5cGV2SnNZZ1JwQXU5T01ZdHdYRUJWNUYreUlCUWtpRzE3YlNlei9z +YgpueW9pV1U2QkFYR2JkQ2pmYTRlVUVURnpiY2xqdEtsZ0FCUkdqV0Q3UEZPNldmcEFqUXBjamFR +cElUNlh6WGZ1CmZXZ3RsbkZrV3lQZFd6Skw0MldZQ3pjYVNySlNGS2Z6TkR2bVIzc25ZTmRwdWxN +WlBLZUZ2bWUyVFpqdVRSUkUKN3U4S1pGeFBqUGQrQThHYW5Cck5QaWpQY0lxNUphQ1p6TDM1ZGhp +WHBiQkMyUzJYeXJLcG1jK1hKUTgycWVPdwpkNmU5b0pWMTNQN0pTc1lhRWp2UVR5TnI2QTZuNDgy +L3FtUmR1MVIzQUFBQkFRQ1c4emFSOU9lTzFwM1hpMTRYCjkwM245Y2NjUlVwZEw4RlJQNnkxaStU +WmY3ZFJaZWt5bVg2Rm1Pam0wL25vVzNIcGVaMmJiRGlBUERadVc0ZlEKbWdaMGd6bG9kRENlSnZQ +cXZTUXNRZUhKNGMyR3NUbjFUczMzWFNUVnhVS3d3amxGdkxqbzJCQXZpQWhmd2FDdwpSbFRoaWtH +L0J0LzBtWE5tMXpwcVlucUFzWldvcmo5VVZBNjJPVzgxQ1VYMS9kVTFrY1JBaWNjbFFsak5TRFhi +CnppYlU3am91enNDM0VVRURwbUdkbVRRWHhYc0I1MVVOaHl5VmgyZ0FWcUMwMDJtSndnRVVzanBx +c2FMNk03M2EKejgzODhvRHBYYnAxQ0tMRHloOHZKcElOSDBqTk5kRDF3V29BUlFlSHMvTmJRRktR +OElOSXZQc1p6MFpHZkc3Lwp1UytKClByaXZhdGUtTUFDOiBmMjY3ZTM0MzYwOTViZDc5OWYwNzQw +NDExZmJhMDM0YzZjOWNiN2VhYzk1ZDg4NDk3ZGVlYmMxNGZjZWQ0ZDU2Cg== diff --git a/test/tests/clone.js b/test/tests/clone.js index 4f2b58d275..f256e85f51 100644 --- a/test/tests/clone.js +++ b/test/tests/clone.js @@ -3,8 +3,6 @@ var assert = require("assert"); var fse = require("fs-extra"); var local = path.join.bind(path, __dirname); var _ = require("lodash"); -const util = require("util"); -const exec = util.promisify(require("child_process").exec); const generatePathWithLength = (base, length) => { @@ -237,62 +235,6 @@ describe("Clone", function() { }); }); - if (process.platform === "win32") { - it("can clone with ssh using old agent with sha1 signing support only", - async function () { - var pageant = local("../../vendor/pageant.exe"); - var old_pageant = local("../../vendor/pageant_sha1.exe"); - var privateKey = local("../../vendor/private.ppk"); - var test = this; - var url = "git@github.com:nodegit/test.git"; - var opts = { - fetchOpts: { - callbacks: { - certificateCheck: () => 0, - credentials: function(url, userName) { - return NodeGit.Credential.sshKeyFromAgent(userName); - } - } - } - }; - - try { - await exec("taskkill /im pageant.exe /f /t"); - } catch (e) { - try { - await exec("taskkill /im pageant_sha1.exe /f /t"); - } catch(e) {} - } - try { - await exec(`powershell -command "Start-Process ${old_pageant} ${privateKey}`); - } catch (e) { - try { - await exec(`powershell -command "Start-Process ${pageant} ${privateKey}`); - } catch (e) {} - return assert.fail("Cannot run old pageant"); - } - - try { - const repo = await Clone(url, clonePath, opts); - test.repository = repo; - } catch(e) { - return assert.fail("Clone error: " + e.message); - } - - try { - await exec("taskkill /im pageant_sha1.exe /f /t"); - } catch(e) {} - - try { - await exec(`powershell -command "Start-Process ${pageant} ${privateKey}`); - } catch (e) { - return assert.fail("Cannot run pageant"); - } - - return assert.ok(test.repository instanceof Repository); - }); - } - it("can clone with ssh", function() { var test = this; var url = "git@github.com:nodegit/test.git"; diff --git a/test/tests/commit.js b/test/tests/commit.js index 69868333cf..8ff9b8ea78 100644 --- a/test/tests/commit.js +++ b/test/tests/commit.js @@ -286,7 +286,7 @@ describe("Commit", function() { it("can amend commit", function(){ var commitToAmendId = "315e77328ef596f3bc065d8ac6dd2c72c09de8a5"; - var expectedAmendedCommitId = "57836e96555243666ea74ea888310cc7c41d4613"; + var expectedAmendedCommitId = "a41de0d1c3dc169c873dd03bd9240d9f88e60ffc"; var fileName = "newfile.txt"; var fileContent = "hello world"; var newFileName = "newerfile.txt"; diff --git a/utils/acquireOpenSSL.mjs b/utils/acquireOpenSSL.mjs index 047b95cb75..930b5ab33c 100644 --- a/utils/acquireOpenSSL.mjs +++ b/utils/acquireOpenSSL.mjs @@ -1,4 +1,5 @@ import crypto from "crypto"; +import { spawn } from "child_process"; import execPromise from "./execPromise.js"; import got from "got"; import path from "path"; @@ -9,6 +10,8 @@ import { createWriteStream, promises as fs } from "fs"; import { performance } from "perf_hooks"; import { promisify } from "util"; +import { hostArch, targetArch } from "./buildFlags.js"; + const pipeline = promisify(stream.pipeline); import packageJson from '../package.json' with { type: "json" }; @@ -19,6 +22,8 @@ const vendorPath = path.resolve(import.meta.dirname, "..", "vendor"); const opensslPatchPath = path.join(vendorPath, "patches", "openssl"); const extractPath = path.join(vendorPath, "openssl"); +const exists = (filePath) => fs.stat(filePath).then(() => true).catch(() => false); + const pathsToIncludeForPackage = [ "include", "lib" ]; @@ -82,8 +87,10 @@ const buildDarwin = async (buildCwd, macOsDeploymentTarget) => { throw new Error("Expected macOsDeploymentTarget to be specified"); } + const buildConfig = targetArch === "x64" ? "darwin64-x86_64-cc" : "darwin64-arm64-cc"; + const configureArgs = [ - process.arch === "x64" ? "darwin64-x86_64-cc" : "darwin64-arm64-cc", + buildConfig, // speed up ecdh on little-endian platforms with 128bit int support "enable-ec_nistp_64_gcc_128", // compile static libraries @@ -107,7 +114,7 @@ const buildDarwin = async (buildCwd, macOsDeploymentTarget) => { await applyOpenSSLPatches(buildCwd, "darwin"); - // only build the libraries, not the tests/fuzzer or apps + // only build the libraries, not the fuzzer or apps await execPromise("make build_libs", { cwd: buildCwd }, { pipeOutput: true }); @@ -123,22 +130,17 @@ const buildDarwin = async (buildCwd, macOsDeploymentTarget) => { }; const buildLinux = async (buildCwd) => { + const buildConfig = targetArch === "x64" ? "linux-x86_64" : "linux-aarch64"; + const configureArgs = [ - "linux-x86_64", - // Electron(at least on centos7) imports the libcups library at runtime, which has a - // dependency on the system libssl/libcrypto which causes symbol conflicts and segfaults. - // To fix this we need to hide all the openssl symbols to prevent them from being overridden - // by the runtime linker. - // "-fvisibility=hidden", - // compile static libraries - "no-shared", - // disable ssl2, ssl3, and compression - "no-ssl2", + buildConfig, + // disable ssl3, and compression "no-ssl3", "no-comp", // set install directory `--prefix="${extractPath}"`, - `--openssldir="${extractPath}"` + `--openssldir="${extractPath}"`, + "--libdir=lib", ]; await execPromise(`./Configure ${configureArgs.join(" ")}`, { cwd: buildCwd @@ -146,14 +148,18 @@ const buildLinux = async (buildCwd) => { await applyOpenSSLPatches(buildCwd, "linux"); - // only build the libraries, not the tests/fuzzer or apps + // only build the libraries, not the fuzzer or apps await execPromise("make build_libs", { - cwd: buildCwd + cwd: buildCwd, + maxBuffer: 10 * 1024 * 1024 }, { pipeOutput: true }); - await execPromise("make test", { - cwd: buildCwd - }, { pipeOutput: true }); + if (hostArch === targetArch) { + await execPromise("make test", { + cwd: buildCwd, + maxBuffer: 10 * 1024 * 1024 + }, { pipeOutput: true }); + } // only install software, not the docs await execPromise("make install_sw", { @@ -162,13 +168,7 @@ const buildLinux = async (buildCwd) => { }, { pipeOutput: true }); }; -const buildWin32 = async (buildCwd, vsBuildArch) => { - if (!vsBuildArch) { - throw new Error("Expected vsBuildArch to be specified"); - } - - const exists = (filePath) => fs.stat(filePath).then(() => true).catch(() => false); - +const buildWin32 = async (buildCwd) => { let vcvarsallPath = undefined; if (process.env.npm_config_vcvarsall_path && await exists(process.env.npm_config_vcvarsall_path)) { @@ -219,29 +219,57 @@ const buildWin32 = async (buildCwd, vsBuildArch) => { } } - console.log('using', vcvarsallPath); - let vcTarget; - switch (vsBuildArch) { - case "x64": { + switch (targetArch) { + case "x64": vcTarget = "VC-WIN64A"; break; - } - case "x86": { + case "x86": vcTarget = "VC-WIN32"; break; - } - - default: { - throw new Error(`Unknown vsBuildArch: ${vsBuildArch}`); - } + + case "arm64": + vcTarget = "VC-WIN64-ARM"; + break; } - await execPromise(`"${win32BatPath}" "${vcvarsallPath}" ${vsBuildArch} ${vcTarget}`, { - cwd: buildCwd, - maxBuffer: 10 * 1024 * 1024 // we should really just use spawn - }, { pipeOutput: true }); + let vsBuildArch = hostArch === targetArch + ? hostArch + : `${hostArch}_${targetArch}`; + + console.log("Using vcvarsall.bat at: ", vcvarsallPath); + console.log("Using vsBuildArch: ", vsBuildArch); + console.log("Using vcTarget: ", vcTarget); + + await new Promise((resolve, reject) => { + const buildProcess = spawn(`"${win32BatPath}" "${vcvarsallPath}" ${vsBuildArch} ${vcTarget}`, { + cwd: buildCwd, + shell: process.platform === "win32", + env: { + ...process.env, + NODEGIT_SKIP_TESTS: targetArch !== hostArch ? "1" : undefined + } + }); + + buildProcess.stdout.on("data", function(data) { + console.info(data.toString().trim()); + }); + + buildProcess.stderr.on("data", function(data) { + console.error(data.toString().trim()); + }); + + buildProcess.on("close", function(code) { + if (!code) { + resolve(); + } else { + reject(code); + } + }); + }); + + }; const removeOpenSSLIfOudated = async (openSSLVersion) => { @@ -285,19 +313,13 @@ const makeOnStreamDownloadProgress = () => { const buildOpenSSLIfNecessary = async ({ macOsDeploymentTarget, - openSSLVersion, - vsBuildArch + openSSLVersion }) => { if (process.platform !== "darwin" && process.platform !== "win32" && process.platform !== "linux") { console.log(`Skipping OpenSSL build, not required on ${process.platform}`); return; } - if (process.platform === "linux" && process.env.NODEGIT_OPENSSL_STATIC_LINK !== "1") { - console.log(`Skipping OpenSSL build, NODEGIT_OPENSSL_STATIC_LINK !== 1`); - return; - } - await removeOpenSSLIfOudated(openSSLVersion); try { @@ -330,7 +352,7 @@ const buildOpenSSLIfNecessary = async ({ } else if (process.platform === "linux") { await buildLinux(buildCwd); } else if (process.platform === "win32") { - await buildWin32(buildCwd, vsBuildArch); + await buildWin32(buildCwd); } else { throw new Error(`Unknown platform: ${process.platform}`); } @@ -348,11 +370,6 @@ const downloadOpenSSLIfNecessary = async ({ return; } - if (process.platform === "linux" && process.env.NODEGIT_OPENSSL_STATIC_LINK !== "1") { - console.log(`Skipping OpenSSL download, NODEGIT_OPENSSL_STATIC_LINK !== 1`); - return; - } - try { await fs.stat(extractPath); console.log("Skipping OpenSSL download, dir exists"); @@ -383,19 +400,16 @@ const downloadOpenSSLIfNecessary = async ({ } export const getOpenSSLPackageName = () => { - let arch = process.arch; - if (process.platform === "win32" && ( - process.arch === "ia32" || process.env.NODEGIT_VS_BUILD_ARCH === "x86" - )) { - arch = "x86"; - } - - return `openssl-${OPENSSL_VERSION}-${process.platform}-${arch}.tar.gz`; + return `openssl-${OPENSSL_VERSION}-${process.platform}-${targetArch}.tar.gz`; } export const getOpenSSLPackagePath = () => path.join(import.meta.dirname, getOpenSSLPackageName()); -const getOpenSSLPackageUrl = () => `${packageJson.binary.host}${getOpenSSLPackageName()}`; +const getOpenSSLPackageUrl = () => { + const hostUrl = new URL(packageJson.binary.host); + hostUrl.pathname = getOpenSSLPackageName(); + return hostUrl.toString(); +}; const buildPackage = async () => { let resolve, reject; @@ -421,7 +435,7 @@ const buildPackage = async () => { createWriteStream(getOpenSSLPackagePath()) ); const digest = await promise; - await fs.writeFile(`${getOpenSSLPackageName()}.sha256`, digest); + await fs.writeFile(`${getOpenSSLPackagePath()}.sha256`, digest); }; const acquireOpenSSL = async () => { @@ -450,18 +464,9 @@ const acquireOpenSSL = async () => { } } - let vsBuildArch; - if (process.platform === "win32") { - vsBuildArch = process.env.NODEGIT_VS_BUILD_ARCH || (process.arch === "x64" ? "x64" : "x86"); - if (!["x64", "x86"].includes(vsBuildArch)) { - throw new Error(`Invalid vsBuildArch: ${vsBuildArch}`); - } - } - await buildOpenSSLIfNecessary({ openSSLVersion: OPENSSL_VERSION, - macOsDeploymentTarget, - vsBuildArch + macOsDeploymentTarget }); if (process.env.NODEGIT_OPENSSL_BUILD_PACKAGE) { await buildPackage(); diff --git a/utils/build-openssl.bat b/utils/build-openssl.bat index 6e146cf891..af8063d7c4 100644 --- a/utils/build-openssl.bat +++ b/utils/build-openssl.bat @@ -1,9 +1,18 @@ +rem Build OpenSSL for Windows +rem %1 - path to vcvarsall.bat +rem %2 - architecture argument for vcvarsall.bat +rem %3 - OpenSSL Configure target + @call %1 %2 perl .\Configure %3 no-shared no-ssl2 no-ssl3 no-comp --prefix="%cd%\.." --openssldir="%cd%\.." || goto :error nmake || goto :error -nmake test || goto :error + +if "%NODEGIT_SKIP_TESTS%" NEQ "1" ( + nmake test || goto :error +) + nmake install || goto :error goto :EOF diff --git a/utils/buildFlags.js b/utils/buildFlags.js index 3c3d9d9b21..7ea87428ba 100644 --- a/utils/buildFlags.js +++ b/utils/buildFlags.js @@ -10,7 +10,29 @@ try { isGitRepo = false; } +const convertArch = (archStr) => { + const convertedArch = { + 'ia32': 'x86', + 'x86': 'x86', + 'x64': 'x64', + 'arm64': 'arm64' + }[archStr]; + + if (!convertedArch) { + throw new Error('unsupported architecture'); + } + + return convertedArch; +} + +const hostArch = convertArch(process.arch); +const targetArch = process.env.npm_config_arch + ? convertArch(process.env.npm_config_arch) + : hostArch; + module.exports = { + hostArch, + targetArch, debugBuild: !!process.env.BUILD_DEBUG, isElectron: process.env.npm_config_runtime === "electron", isGitRepo: isGitRepo, diff --git a/utils/configureLibssh2.js b/utils/configureLibssh2.js index 95328ebdb2..95fd5d3649 100644 --- a/utils/configureLibssh2.js +++ b/utils/configureLibssh2.js @@ -2,6 +2,8 @@ var cp = require("child_process"); var fse = require("fs-extra"); var path = require("path"); +const { hostArch, targetArch } = require("./buildFlags"); + const opensslVendorDirectory = path.resolve(__dirname, "..", "vendor", "openssl"); const libssh2VendorDirectory = path.resolve(__dirname, "..", "vendor", "libssh2"); const libssh2ConfigureScript = path.join(libssh2VendorDirectory, "configure"); @@ -19,20 +21,21 @@ module.exports = function retrieveExternalDependencies() { } // Run the `configure` script on Linux + let cpArgs = ` --with-libssl-prefix=${opensslVendorDirectory}`; + + const archConfigMap = { + 'x64': 'x86_64-linux-gnu', + 'arm64': 'aarch64-linux-gnu' + }; + + cpArgs += ` --build=${archConfigMap[hostArch]}`; + cpArgs += ` --host=${archConfigMap[targetArch]}`; + return new Promise(function(resolve, reject) { - var newEnv = {}; - Object.keys(process.env).forEach(function(key) { - newEnv[key] = process.env[key]; - }); - - let cpArgs = process.env.NODEGIT_OPENSSL_STATIC_LINK === '1' - ? ` --with-libssl-prefix=${opensslVendorDirectory}` - : ''; cp.exec( `${libssh2ConfigureScript}${cpArgs}`, { - cwd: libssh2VendorDirectory, - env: newEnv + cwd: libssh2VendorDirectory }, function(err, stdout, stderr) { if (err) { diff --git a/utils/uploadOpenSSL.mjs b/utils/uploadOpenSSL.mjs index 86495e98e7..5de760462e 100644 --- a/utils/uploadOpenSSL.mjs +++ b/utils/uploadOpenSSL.mjs @@ -19,7 +19,9 @@ export const uploadOpenSSL = async () => { const packageName = path.basename(getOpenSSLPackageName()); const packagePath = getOpenSSLPackagePath(); console.log(`Uploading ${packagePath} to s3://${pkgJson.binary.bucket_name}/${packageName}`); - return uploadBinaryToS3(packageName, pkgJson.binary.bucket_name, packagePath); + await uploadBinaryToS3(packageName, pkgJson.binary.bucket_name, packagePath); + const sha256PackageName = `${packageName}.sha256`; + await uploadBinaryToS3(sha256PackageName, pkgJson.binary.bucket_name, `${packagePath}.sha256`); }; if (process.argv[1] === import.meta.filename) { diff --git a/vendor/libgit2.gyp b/vendor/libgit2.gyp index a155fb67fb..aff29d76a2 100644 --- a/vendor/libgit2.gyp +++ b/vendor/libgit2.gyp @@ -11,7 +11,6 @@ "is_clang%": 0, "is_IBMi%": "