diff --git a/.travis.yml b/.travis.yml index 891a60818..77d182cb3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,37 +1,49 @@ +sudo: false + branches: only: - master - /^v\d+\.\d+\.\d+$/ compiler: clang +language: node_js + +# Stage order; the default stage is "test", which in our case is actually building and deploying +stages: + - "Extended testing" + - test + - "Deploy documentation" + +env: + - TARGET_ARCH="x64" + - TARGET_ARCH="ia32" + +node_js: + - "9" + - "8" + - "6" os: - linux - osx -sudo: false - -env: - matrix: - - export NODE_VERSION="9.6" TARGET_ARCH="x64" - - export NODE_VERSION="8.9" TARGET_ARCH="x64" - - export NODE_VERSION="7.10" TARGET_ARCH="x64" - - export NODE_VERSION="6.13" TARGET_ARCH="x64" - -matrix: - fast_finish: true +jobs: + exclude: + - os: osx + env: TARGET_ARCH="ia32" include: - - os: linux - env: export NODE_VERSION="9.6" TARGET_ARCH="ia32" - - os: linux - env: export NODE_VERSION="8.9" TARGET_ARCH="ia32" - - os: linux - env: export NODE_VERSION="7.10" TARGET_ARCH="ia32" - - os: linux - env: export NODE_VERSION="6.13" TARGET_ARCH="ia32" + - stage: "Extended testing" + os: linux + node_js: "8" + env: TARGET_ARCH="x64" EXTENDED_TESTING="false" + - stage: "Deploy documentation" + os: linux + node_js: "8" + env: TARGET_ARCH="x64" DEPLOY_DOCUMENTATION="true" + git: - depth: 1 + depth: 5 addons: apt: @@ -50,14 +62,7 @@ before_install: - export npm_config_clang=1 - export JOBS=4 - - if [ $TRAVIS_OS_NAME != "linux" ]; then - git clone https://github.com/creationix/nvm.git ./.nvm; - source ./.nvm/nvm.sh; - fi - - - nvm install $NODE_VERSION - - - if [ -z "$TRAVIS_TAG" ] && [ $TRAVIS_OS_NAME == "linux" ] && [ $NODE_VERSION == "6" ]; then + - if [ -z "$TRAVIS_TAG" ] && [ "$EXTENDED_TESTING" == "true" ]; then export GYP_DEFINES="coverage=1 use_obsolete_asm=true"; export CC=/usr/bin/gcc-4.9; export CXX=/usr/bin/g++-4.9; @@ -83,7 +88,7 @@ before_script: - git config --global user.email johndoe@example.com script: - if [ -z "$TRAVIS_TAG" ] && [ $TRAVIS_OS_NAME == "linux" ] && [ $NODE_VERSION == "6" ]; then + if [ -z "$TRAVIS_TAG" ] && [ "$EXTENDED_TESTING" == "true" ]; then travis_retry npm test && npm run cov && npm run coveralls; else travis_retry npm test; @@ -98,7 +103,7 @@ after_success: node-pre-gyp publish --target_arch=$TARGET_ARCH; fi - - if [ $TRAVIS_BRANCH == "master" ] && [ $TRAVIS_PULL_REQUEST == "false" ] && [ $TRAVIS_OS_NAME == "linux" ] && [ $NODE_VERSION == "6" ] && [ $TARGET_ARCH == "x64" ]; then + - if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ -n "$TRAVIS_TAG" ] && [ "$DEPLOY_DOCUMENTATION" == "true" ]; then .travis/deploy-docs.sh; fi diff --git a/CHANGELOG.md b/CHANGELOG.md index 41cf4aa5e..5b21f4837 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,32 @@ # Change Log +## v0.21.2v0.21.1 [(2018-03-05)](https://github.com/nodegit/nodegit/releases/tag/v0.21.1) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.21.0...v0.21.1) @@ -14,7 +41,7 @@ [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.20.3...v0.21.0) -### Summary of changes to NodeGit: +#### Summary of changes to NodeGit: - [Generate default options for Revert.revert to prevent an exception #1404](https://github.com/nodegit/nodegit/pull/1404) - [fix issue with re-require()'ing native modules #1354](https://github.com/nodegit/nodegit/pull/1354) - [Expose JavaScript function name in a rejected promise #1393](https://github.com/nodegit/nodegit/pull/1393) @@ -29,7 +56,7 @@ - [Fix details-for-tree-entry.js to access fields instead of calling a function #1326](https://github.com/nodegit/nodegit/pull/1326) - [Add JavaScript version of `git_tag_peel()` #1269](https://github.com/nodegit/nodegit/pull/1269) - [Fixed documentation error #1417](https://github.com/nodegit/nodegit/pull/1417) - - [Annoate Blame.file as async #1421](https://github.com/nodegit/nodegit/pull/1421) + - [Annotate Blame.file as async #1421](https://github.com/nodegit/nodegit/pull/1421) - [Add two missing tests to Commit #1422](https://github.com/nodegit/nodegit/pull/1422) - [CI: Update Node.js versions + some deps #1444](https://github.com/nodegit/nodegit/pull/1444) - [Expose fetch_options.custom_headers #1430](https://github.com/nodegit/nodegit/pull/1430) @@ -117,7 +144,7 @@ - [Add CI build config for node stable version #1337](https://github.com/nodegit/nodegit/pull/1337) - [removed node v4 tests #1330](https://github.com/nodegit/nodegit/pull/1330) -#### Included merged libgti2 PRs: +#### Included merged libgit2 PRs: - [Include fixups #4288](https://github.com/libgit2/libgit2/pull/4288) - [Docs: Fix inline comments for git_diff_hunk #4330](https://github.com/libgit2/libgit2/pull/4330) - [oid: use memcmp in git_oid__hashcmp #4328](https://github.com/libgit2/libgit2/pull/4328) @@ -193,7 +220,7 @@ #### Summary of changes outside of libgit2 bump: - You can now convert tree entries in blobs [PR #1272](https://github.com/nodegit/nodegit/pull/1272) -#### Included merged libgti2 PRs: +#### Included merged libgit2 PRs: - [fileops: fix leaking fd in `mmap_ro_file` #4201](https://github.com/libgit2/libgit2/pull/4201) - [README: document our relation to changes in upstream #4198](https://github.com/libgit2/libgit2/pull/4198) diff --git a/appveyor.yml b/appveyor.yml index fb0c1a02c..acbc2bcc9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -28,7 +28,6 @@ environment: # Node.js - nodejs_version: "9" - nodejs_version: "8" - - nodejs_version: "7" - nodejs_version: "6" matrix: diff --git a/generate/input/descriptor.json b/generate/input/descriptor.json index 54d611ac0..fde52a83a 100644 --- a/generate/input/descriptor.json +++ b/generate/input/descriptor.json @@ -523,7 +523,7 @@ "ignore": true }, "git_commit_extract_signature": { - "ignore": true + "isAsync": true }, "git_commit_id": { "return": { @@ -576,13 +576,40 @@ "ignore": true }, "git_config_find_global": { - "ignore": true + "isAsync": true, + "args": { + "out": { + "isReturn": true, + "shouldAlloc": true + } + }, + "return": { + "isErrorCode": true + } }, "git_config_find_system": { - "ignore": true + "isAsync": true, + "args": { + "out": { + "isReturn": true, + "shouldAlloc": true + } + }, + "return": { + "isErrorCode": true + } }, "git_config_find_xdg": { - "ignore": true + "isAsync": true, + "args": { + "out": { + "isReturn": true, + "shouldAlloc": true + } + }, + "return": { + "isErrorCode": true + } }, "git_config_foreach": { "ignore": true @@ -627,7 +654,16 @@ } }, "git_config_get_path": { - "ignore": true + "isAsync": true, + "args": { + "out": { + "isReturn": true, + "shouldAlloc": true + } + }, + "return": { + "isErrorCode": true + } }, "git_config_iterator_free": { "ignore": true @@ -666,7 +702,15 @@ "ignore": true }, "git_config_open_ondisk": { - "ignore": true + "isAsync": true, + "return": { + "isErrorCode": true + }, + "args": { + "out": { + "isReturn": true + } + } }, "git_config_parse_bool": { "ignore": true diff --git a/generate/input/libgit2-supplement.json b/generate/input/libgit2-supplement.json index 3e0d24fd7..a31e54f2b 100644 --- a/generate/input/libgit2-supplement.json +++ b/generate/input/libgit2-supplement.json @@ -86,6 +86,40 @@ }, "new" : { "functions": { + "git_commit_extract_signature": { + "args": [ + { + "name": "signature", + "type": "git_buf" + }, + { + "name": "signed_data", + "type": "git_buf" + }, + { + "name": "repo", + "type": "git_repository *" + }, + { + "name": "commit_id", + "type": "git_oid *" + }, + { + "name": "field", + "type": "char *" + } + ], + "type": "function", + "isManual": true, + "cFile": "generate/templates/manual/commit/extract_signature.cc", + "isAsync": true, + "isPrototypeMethod": false, + "group": "commit", + "return": { + "type": "int", + "isErrorCode": true + } + }, "git_patch_convenient_from_diff": { "args": [ { diff --git a/generate/templates/manual/commit/extract_signature.cc b/generate/templates/manual/commit/extract_signature.cc new file mode 100644 index 000000000..581eef6b8 --- /dev/null +++ b/generate/templates/manual/commit/extract_signature.cc @@ -0,0 +1,156 @@ +NAN_METHOD(GitCommit::ExtractSignature) +{ + if (info.Length() == 0 || !info[0]->IsObject()) { + return Nan::ThrowError("Repository repo is required."); + } + + if (info.Length() == 1 || (!info[1]->IsObject() && !info[1]->IsString())) { + return Nan::ThrowError("Oid commit_id is required."); + } + + if (info.Length() == 2 || (info.Length() == 3 && !info[2]->IsFunction())) { + return Nan::ThrowError("Callback is required and must be a Function."); + } + + if (info.Length() >= 4) { + if (!info[2]->IsString() && !info[2]->IsUndefined() && !info[2]->IsNull()) { + return Nan::ThrowError("String signature_field must be a string or undefined/null."); + } + + if (!info[3]->IsFunction()) { + return Nan::ThrowError("Callback is required and must be a Function."); + } + } + + ExtractSignatureBaton* baton = new ExtractSignatureBaton; + + baton->error_code = GIT_OK; + baton->error = NULL; + baton->signature = GIT_BUF_INIT_CONST(NULL, 0); + baton->signed_data = GIT_BUF_INIT_CONST(NULL, 0); + baton->repo = Nan::ObjectWrap::Unwrap(info[0]->ToObject())->GetValue(); + + // baton->commit_id + if (info[1]->IsString()) { + String::Utf8Value oidString(info[1]->ToString()); + baton->commit_id = (git_oid *)malloc(sizeof(git_oid)); + if (git_oid_fromstr(baton->commit_id, (const char *)strdup(*oidString)) != GIT_OK) { + free(baton->commit_id); + + if (giterr_last()) { + return Nan::ThrowError(giterr_last()->message); + } else { + return Nan::ThrowError("Unknown Error"); + } + } + } else { + baton->commit_id = Nan::ObjectWrap::Unwrap(info[1]->ToObject())->GetValue(); + } + + // baton->field + if (info[2]->IsString()) { + String::Utf8Value field(info[2]->ToString()); + baton->field = (char *)malloc(field.length() + 1); + memcpy((void *)baton->field, *field, field.length()); + baton->field[field.length()] = 0; + } else { + baton->field = NULL; + } + + Nan::Callback *callback; + if (info[2]->IsFunction()) { + callback = new Nan::Callback(Local::Cast(info[2])); + } else { + callback = new Nan::Callback(Local::Cast(info[3])); + } + + ExtractSignatureWorker *worker = new ExtractSignatureWorker(baton, callback); + worker->SaveToPersistent("repo", info[0]->ToObject()); + worker->SaveToPersistent("commit_id", info[1]->ToObject()); + Nan::AsyncQueueWorker(worker); + return; +} + +void GitCommit::ExtractSignatureWorker::Execute() +{ + giterr_clear(); + + { + LockMaster lockMaster( + /*asyncAction: */true, + baton->repo + ); + + baton->error_code = git_commit_extract_signature( + &baton->signature, + &baton->signed_data, + baton->repo, + baton->commit_id, + (const char *)baton->field + ); + + if (baton->error_code != GIT_OK && giterr_last() != NULL) { + baton->error = git_error_dup(giterr_last()); + } + } +} + +void GitCommit::ExtractSignatureWorker::HandleOKCallback() +{ + if (baton->error_code == GIT_OK) + { + Local result = Nan::New(); + Nan::Set( + result, + Nan::New("signature").ToLocalChecked(), + Nan::New(baton->signature.ptr, baton->signature.size).ToLocalChecked() + ); + Nan::Set( + result, + Nan::New("signedData").ToLocalChecked(), + Nan::New(baton->signed_data.ptr, baton->signed_data.size).ToLocalChecked() + ); + + Local argv[2] = { + Nan::Null(), + result + }; + callback->Call(2, argv); + } + else if (baton->error) + { + Local argv[1] = { + Nan::Error(baton->error->message) + }; + callback->Call(1, argv); + if (baton->error->message) + { + free((void *)baton->error->message); + } + + free((void *)baton->error); + } + else if (baton->error_code < 0) + { + Local err = Nan::Error("Extract Signature has thrown an error.")->ToObject(); + err->Set(Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code)); + err->Set(Nan::New("errorFunction").ToLocalChecked(), Nan::New("Commit.extractSignature").ToLocalChecked()); + Local argv[1] = { + err + }; + callback->Call(1, argv); + } + else + { + callback->Call(0, NULL); + } + + git_buf_free(&baton->signature); + git_buf_free(&baton->signed_data); + + if (baton->field != NULL) { + free((void *)baton->field); + } + + delete baton; +} diff --git a/lib/commit.js b/lib/commit.js index 73d3f62b4..232d771b0 100644 --- a/lib/commit.js +++ b/lib/commit.js @@ -4,6 +4,7 @@ var Commit = NodeGit.Commit; var LookupWrapper = NodeGit.Utils.lookupWrapper; var _amend = Commit.prototype.amend; + /** * Retrieves the commit pointed to by the oid * @async @@ -162,6 +163,23 @@ Commit.prototype.getParents = function(limit, callback) { }, callback); }; +/** + * @typedef extractedSignature + * @type {Object} + * @property {String} signature the signature of the commit + * @property {String} signedData the extracted signed data + */ + +/** + * Retrieve the signature and signed data for a commit. + * @param {String} field Optional field to get from the signature, + * defaults to gpgsig + * @return {extractedSignature} + */ +Commit.prototype.getSignature = function(field) { + return Commit.extractSignature(this.repo, this.id(), field); +}; + /** * Get the tree associated with this commit. * diff --git a/lib/repository.js b/lib/repository.js index 56d2f5a6f..d876b1241 100644 --- a/lib/repository.js +++ b/lib/repository.js @@ -204,12 +204,21 @@ function performRebase( ) { var beforeNextFnResult; - function readRebaseMetadataFile(fileName) { + /* In the case of FF merges and a beforeFinishFn, this will fail + * when looking for 'rewritten' so we need to handle that case. + */ + function readRebaseMetadataFile(fileName, continueOnError) { return fse.readFile( path.join(repository.path(), "rebase-merge", fileName), { encoding: "utf8" } ) - .then(fp.trim); + .then(fp.trim) + .catch(function(err) { + if (continueOnError) { + return null; + } + throw err; + }); } function calcHeadName(input) { @@ -240,9 +249,12 @@ function performRebase( }) .catch(function(error) { if (error && error.errno === NodeGit.Error.CODE.ITEROVER) { - const calcRewritten = fp.flow([ - fp.split("\n"), - fp.map(fp.split(" ")) + const calcRewritten = fp.cond([ + [fp.isEmpty, fp.constant(null)], + [fp.stubTrue, fp.flow([ + fp.split("\n"), + fp.map(fp.split(" ")) + ])] ]); const beforeFinishFnPromise = !beforeFinishFn ? @@ -252,7 +264,7 @@ function performRebase( readRebaseMetadataFile("onto"), readRebaseMetadataFile("head-name").then(calcHeadName), readRebaseMetadataFile("orig-head"), - readRebaseMetadataFile("rewritten").then(calcRewritten) + readRebaseMetadataFile("rewritten", true).then(calcRewritten) ]) .then(function([ ontoName, diff --git a/lib/tree_entry.js b/lib/tree_entry.js index a65d85172..b9bc0fd72 100644 --- a/lib/tree_entry.js +++ b/lib/tree_entry.js @@ -1,4 +1,4 @@ -var path = require("path"); +var path = require("path").posix; var NodeGit = require("../"); var TreeEntry = NodeGit.TreeEntry; diff --git a/package-lock.json b/package-lock.json index cda103de2..6d7b069eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "nodegit", - "version": "0.21.1", + "version": "0.21.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 507ac1e63..1062b4010 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "nodegit", "description": "Node.js libgit2 asynchronous native bindings", - "version": "0.21.1", + "version": "0.21.2", "homepage": "http://nodegit.org", "keywords": [ "libgit2", diff --git a/test/tests/commit.js b/test/tests/commit.js index 94d357a0a..181a1461b 100644 --- a/test/tests/commit.js +++ b/test/tests/commit.js @@ -718,4 +718,43 @@ describe("Commit", function() { // the self-freeing signature should get freed assert.equal(startSelfFreeingCount, endSelfFreeingCount); }); + + describe("Commit's Signature", function() { + it("Can retrieve the gpg signature from a commit", function() { + var expectedSignedData = + "tree f4661419a6fbbe865f78644fec722c023ce4b65f\n" + + "parent 32789a79e71fbc9e04d3eff7425e1771eb595150\n" + + "author Tyler Ang-Wanek 1521227848 -0700\n" + + "committer Tyler Ang-Wanek 1521227848 -0700\n\n" + + "GPG Signed commit\n"; + + var expectedSignature = + "-----BEGIN PGP SIGNATURE-----\n\n" + + "iQEcBAABCAAGBQJarBhIAAoJEE8pfTd/81lKQA4IAL8Mu5kc4B/MX9s4XB26Ahap\n" + + "n06kCx3RQ1KHMZIRomAjCnb48WieNVuy1y+Ut0RgfCxxrJ1ZnzFG3kF2bIKwIxNI\n" + + "tYIC76iWny+mrVnb2mjKYjn/3F4c4VJGENq9ITiV1WeE4yJ8dHw2ox2D+hACzTvQ\n" + + "KVroedk8BDFJxS6DFb20To35xbAVhwBnAGRcII4Wi5PPMFpqAhGLfq3Czv95ddSz\n" + + "BHlyp27+YWSpV0Og0dqOEhsdDYaPrOBGRcoRiqjue+l5tgK/QerLFZ4aovZzpuEP\n" + + "Xx1yZfqXIiy4Bo40qScSrdnmnp/kMq/NQGR3jYU+SleFHVKNFsya9UwurMaezY0=\n" + + "=eZzi\n-----END PGP SIGNATURE-----"; + + return NodeGit.Commit.lookup( + this.repository, + "cc1401eaac4e9e77190e98a9353b305f0c6313d8" + ) + .then(function(commit) { + return commit.getSignature(); + }) + .then(function(extractSignature) { + assert.equal( + extractSignature.signature, + expectedSignature + ); + assert.equal( + extractSignature.signedData, + expectedSignedData + ); + }); + }); + }); }); diff --git a/test/tests/config.js b/test/tests/config.js index 3ac6fca48..bc4b802f3 100644 --- a/test/tests/config.js +++ b/test/tests/config.js @@ -6,9 +6,104 @@ var exec = require("../../utils/execPromise"); describe("Config", function() { var NodeGit = require("../../"); + var Repository = NodeGit.Repository; + var Config = NodeGit.Config; var reposPath = local("../repos/workdir"); + describe("openOnDisk", function() { + var configPath = path.join(reposPath, ".git/config"); + + it("opens the same config as the repo", function() { + var repo; + var onDiskConfig; + return Repository.open(reposPath) + .then(function(_repo) { + repo = _repo; + return Config.openOndisk(configPath); + }) + .then(function(config) { + onDiskConfig = config; + return repo.config(); + }) + .then(function(repoConfig) { + return Promise.all([ + onDiskConfig.getString("core.filemode"), + onDiskConfig.getString("core.bare"), + repoConfig.getString("core.filemode"), + repoConfig.getString("core.bare") + ]); + }) + .then(function(results) { + var onDiskFileMode = results[0]; + var onDiskBare = results[1]; + var repoFileMode = results[2]; + var repoBare = results[3]; + + assert.equal(onDiskFileMode, repoFileMode); + assert.equal(onDiskBare, repoBare); + }); + }); + + it("opens the config and can change a value", function() { + var repo; + var onDiskConfig; + var repoConfig; + var originalFileMode; + return Repository.open(reposPath) + .then(function(_repo) { + repo = _repo; + return Config.openOndisk(configPath); + }) + .then(function(config) { + onDiskConfig = config; + return repo.config(); + }) + .then(function(_repoConfig) { + repoConfig = _repoConfig; + return Promise.all([ + onDiskConfig.getString("core.filemode"), + repoConfig.getString("core.filemode") + ]); + }) + .then(function(results) { + var onDiskFileMode = results[0]; + var repoFileMode = results[1]; + + assert.equal(onDiskFileMode, repoFileMode); + originalFileMode = onDiskFileMode; + var oppositeFileMode = onDiskFileMode === "true" ? "false" : "true"; + + return onDiskConfig.setString( + "core.filemode", + oppositeFileMode + ); + }) + .then(function() { + return Config.openOndisk(configPath); + }) + .then(function(config) { + return Promise.all([ + config.getString("core.filemode"), + repoConfig.getString("core.filemode") + ]); + }) + .then(function(results) { + var onDiskFileMode = results[0]; + var repoFileMode = results[1]; + assert.notEqual(onDiskFileMode, originalFileMode); + assert.equal(onDiskFileMode, repoFileMode); + }) + .then(function() { + // cleanup + return onDiskConfig.setString( + "core.filemode", + originalFileMode + ); + }); + }); + }); + it("can get and set a global value", function() { var savedUserName; @@ -92,4 +187,24 @@ describe("Config", function() { }); }); }); + + describe("getPath", function() { + it("can get path for a given config", function() { + return NodeGit.Repository.open(reposPath) + .then(function(repo) { + return repo.config(); + }) + .then(function(config) { + return Promise.all([ + config.getPath("core.filemode"), + config.getString("core.filemode") + ]); + }) + .then(function(results) { + var localFilemode = results[0]; + var repoFilemode = results[1]; + assert.equal(localFilemode, repoFilemode); + }); + }); + }); }); diff --git a/test/tests/rebase.js b/test/tests/rebase.js index d121a6c0f..f9dd3d2a2 100644 --- a/test/tests/rebase.js +++ b/test/tests/rebase.js @@ -6,6 +6,8 @@ var fse = promisify(require("fs-extra")); describe("Rebase", function() { var NodeGit = require("../../"); + var Checkout = NodeGit.Checkout; + var Merge = NodeGit.Merge; var RepoUtils = require("../utils/repository_setup"); var repoPath = local("../repos/rebase"); @@ -790,6 +792,168 @@ describe("Rebase", function() { }); }); + it( + "can fast-forward a merge commit via rebase using the " + + "convenience methods that has a beforeFinishFn", + function() { + var ourFileName = "ourNewFile.txt"; + var theirFileName = "theirNewFile.txt"; + var theirOtherFileName = "antherNewFile.txt"; + + var ourFileContent = "I like Toll Roads. I have an EZ-Pass!"; + var theirFileContent = "I'm skeptical about Toll Roads"; + var theirOtherFileContent = "This is some more content, guys!"; + + var ourSignature = NodeGit.Signature.create + ("Ron Paul", "RonPaul@TollRoadsRBest.info", 123456789, 60); + var theirSignature = NodeGit.Signature.create + ("Greg Abbott", "Gregggg@IllTollYourFace.us", 123456789, 60); + var theirOtherSignature = NodeGit.Signature.create + ("Greg Abbott", "Gregggg@IllTollYourFace.us", 123456999, 60); + var ourMergeSignature = NodeGit.Signature.create + ("Ron Paul", "RonPaul@TollRoadsRBest.info", 123456889, 60); + + var repository = this.repository; + var ourCommit; + var theirCommit; + var theirBranch; + var ourBranch; + + return fse.writeFile(path.join(repository.workdir(), ourFileName), + ourFileContent) + // Load up the repository index and make our initial commit to HEAD + .then(function() { + return RepoUtils.addFileToIndex(repository, ourFileName); + }) + .then(function(oid) { + assert.equal(oid.toString(), + "11ead82b1135b8e240fb5d61e703312fb9cc3d6a"); + + return repository.createCommit("HEAD", ourSignature, + ourSignature, "we made a commit", oid, []); + }) + .then(function(commitOid) { + assert.equal(commitOid.toString(), + "91a183f87842ebb7a9b08dad8bc2473985796844"); + + return repository.getCommit(commitOid).then(function(commit) { + ourCommit = commit; + }).then(function() { + return repository.createBranch(ourBranchName, commitOid) + .then(function(branch) { + ourBranch = branch; + return repository.createBranch(theirBranchName, commitOid); + }); + }); + }) + .then(function(branch) { + theirBranch = branch; + return fse.writeFile(path.join(repository.workdir(), theirFileName), + theirFileContent); + }) + .then(function() { + return RepoUtils.addFileToIndex(repository, theirFileName); + }) + .then(function(oid) { + assert.equal(oid.toString(), + "76631cb5a290dafe2959152626bb90f2a6d8ec94"); + + return repository.createCommit(theirBranch.name(), theirSignature, + theirSignature, "they made a commit", oid, [ourCommit]); + }) + .then(function(commitOid) { + theirCommit = commitOid; + assert.equal(commitOid.toString(), + "0e9231d489b3f4303635fc4b0397830da095e7e7"); + }) + .then(function() { + return repository.checkoutBranch( + ourBranch, + { checkoutStrategy: Checkout.STRATEGY.FORCE } + ); + }) + .then(function() { + return repository.mergeBranches( + ourBranchName, + theirBranchName, + ourMergeSignature, + Merge.PREFERENCE.NO_FASTFORWARD + ); + }) + .then(function() { + return repository.getHeadCommit(); + }) + .then(function(headCommit) { + assert.notEqual(ourCommit.id().toString(), headCommit.id().toString()); + }) + .then(function() { + return repository.checkoutBranch( + theirBranch, + { checkoutStrategy: Checkout.STRATEGY.FORCE } + ); + }) + .then(function() { + return fse.writeFile( + path.join(repository.workdir(), theirOtherFileName), + theirOtherFileContent + ); + }) + .then(function() { + return RepoUtils.addFileToIndex(repository, theirOtherFileName); + }) + .then(function(oid) { + assert.equal(oid.toString(), + "c242b53f2c9446544cf9bdac7e8ed6ce583226cb"); + + return repository.createCommit(theirBranch.name(), theirOtherSignature, + theirOtherSignature, "they made another commit", oid, [theirCommit]); + }) + .then(function(commitOid) { + assert.equal(commitOid.toString(), + "8fa0ce25a2accf464b004ddeeb63add7b816b627"); + }) + .then(function() { + return Promise.all([ + repository.getReference(ourBranchName), + repository.getReference(theirBranchName) + ]); + }) + .then(function(refs) { + assert.equal(refs.length, 2); + + return Promise.all([ + NodeGit.AnnotatedCommit.fromRef(repository, refs[0]), + NodeGit.AnnotatedCommit.fromRef(repository, refs[1]) + ]); + }) + .then(function(annotatedCommits) { + assert.equal(annotatedCommits.length, 2); + + var ourAnnotatedCommit = annotatedCommits[0]; + var theirAnnotatedCommit = annotatedCommits[1]; + + assert.equal(ourAnnotatedCommit.id().toString(), + "0d1d322b59df68bac6eea6a2a189f974cb590368"); + assert.equal(theirAnnotatedCommit.id().toString(), + "8fa0ce25a2accf464b004ddeeb63add7b816b627"); + + return repository.rebaseBranches( + ourBranchName, + theirBranchName, + null, + ourSignature, + null, + function(rebaseData) { + assert.equal(rebaseData.rewritten, null); + } + ); + }) + .then(function(commit) { + assert.equal(commit.id().toString(), + "8fa0ce25a2accf464b004ddeeb63add7b816b627"); + }); + }); + it("can rebase using the convenience method", function() { var baseFileName = "baseNewFile.txt"; var ourFileName = "ourNewFile.txt"; diff --git a/test/tests/tag.js b/test/tests/tag.js index 55f1d71e4..e7b485a1d 100644 --- a/test/tests/tag.js +++ b/test/tests/tag.js @@ -230,4 +230,21 @@ describe("Tag", function() { assert.equal(object.isCommit(), true); }); }); + + it("can get tag's target id", function() { + return this.repository.getTagByName(tagName) + .then(function(tag) { + assert.equal(commitPointedTo, tag.targetId()); + }); + }); + + it("can get tag's owner", function() { + var repository = this.repository; + return this.repository.getTagByName(tagName) + .then(function(tag) { + var owner = tag.owner(); + assert.ok(owner instanceof Repository); + assert.equal(repository.path(), owner.path()); + }); + }); }); diff --git a/test/tests/tree.js b/test/tests/tree.js index aa98d4f3d..0790759f5 100644 --- a/test/tests/tree.js +++ b/test/tests/tree.js @@ -44,8 +44,7 @@ describe("Tree", function() { var repo = this.repository; var file1 = "test.txt"; var file2 = "foo/bar.txt"; - // index.addByPath doesn't like \s so normalize only for the expected paths - var expectedPaths = [file1, path.normalize(file2)]; + var expectedPaths = [file1, file2]; var progressEntries = []; var endEntries; diff --git a/test/tests/tree_entry.js b/test/tests/tree_entry.js index 13093fdaa..086a4f8d2 100644 --- a/test/tests/tree_entry.js +++ b/test/tests/tree_entry.js @@ -57,7 +57,7 @@ describe("TreeEntry", function() { it("provides the full path", function() { return this.commit.getEntry("test/raw-commit.js") .then(function(entry) { - assert.equal(entry.path(), path.normalize("test/raw-commit.js")); + assert.equal(entry.path(), "test/raw-commit.js"); }); }); @@ -66,7 +66,7 @@ describe("TreeEntry", function() { var dir = _dir || "", testPromises = []; tree.entries().forEach(function(entry) { - var currentPath = path.join(dir, entry.name()); + var currentPath = path.posix.join(dir, entry.name()); if (entry.isTree()) { testPromises.push( entry.getTree().then(function (subtree) {