diff --git a/.jshintrc b/.jshintrc index ea2e2b7b1..5f5082b77 100644 --- a/.jshintrc +++ b/.jshintrc @@ -12,6 +12,7 @@ "unused": "vars", "undef": true, "validthis": true, + "futurehostile": true, "globals": { "global": true, "define": true, diff --git a/generate/input/descriptor.json b/generate/input/descriptor.json index 6c4da260c..507a82a23 100644 --- a/generate/input/descriptor.json +++ b/generate/input/descriptor.json @@ -1605,6 +1605,42 @@ "git_tag_foreach": { "ignore": true }, + "git_tag_create": { + "args": { + "oid": { + "isReturn": true + } + }, + "return": { + "isErrorCode": true + }, + "isAsync": true + }, + "git_tag_create_frombuffer": { + "ignore": true + }, + "git_tag_create_lightweight": { + "args": { + "oid": { + "isReturn": true + } + }, + "return": { + "isErrorCode": true + }, + "isAsync": true + }, + "git_tag_annotation_create": { + "args": { + "oid": { + "isReturn": true + } + }, + "return": { + "isErrorCode": true + }, + "isAsync": true + }, "git_tag_list": { "args": { "tag_names": { @@ -1624,6 +1660,12 @@ "isReturn": true } } + }, + "git_tag_delete": { + "return": { + "isErrorCode": true + }, + "isAsync": true } } }, diff --git a/lib/repository.js b/lib/repository.js index 4034ca458..878052f13 100644 --- a/lib/repository.js +++ b/lib/repository.js @@ -268,6 +268,51 @@ Repository.prototype.getTree = function(oid, callback) { }, callback); }; +/** + * Creates a new annotated tag + * + * @async + * @param {String|Oid} String sha or Oid + * @param {String} name the name of the tag + * @param {String} message the description that will be attached to the + * annotated tag + * @return {Tag} + */ +Repository.prototype.createTag = function(oid, name, message, callback) { + var repository = this; + var signature = repository.defaultSignature(); + + return Commit.lookup(repository, oid) + .then(function(commit) { + // Final argument is `force` which overwrites any previous tag + return Tag.create(repository, name, commit, signature, message, 0); + }) + .then(function(tagOid) { + return repository.getTag(tagOid, callback); + }); +}; + +/** + * Creates a new lightweight tag + * + * @async + * @param {String|Oid} String sha or Oid + * @param {String} name the name of the tag + * @return {Reference} + */ +Repository.prototype.createLightweightTag = function(oid, name, callback) { + var repository = this; + + return Commit.lookup(repository, oid) + .then(function(commit) { + // Final argument is `force` which overwrites any previous tag + return Tag.createLightweight(repository, name, commit, 0); + }) + .then(function() { + return Reference.lookup(repository, "refs/tags/" + name); + }); +}; + /** * Retrieve the tag represented by the oid. * @@ -314,6 +359,20 @@ Repository.prototype.getTagByName = function(name, callback) { }, callback); }; +/** + * Deletes a tag from a repository by the tag name. + * + * @async + * @param {String} Short or full tag name + */ +Repository.prototype.deleteTagByName = function(name) { + var repository = this; + + name = ~name.indexOf("refs/tags/") ? name.substr(10) : name; + + return Tag.delete(repository, name); +}; + /** * Instantiate a new revision walker for browsing the Repository"s history. * See also `Commit.prototype.history()` diff --git a/test/tests/tag.js b/test/tests/tag.js index 1f2ffca00..484e48f56 100644 --- a/test/tests/tag.js +++ b/test/tests/tag.js @@ -7,6 +7,8 @@ describe("Tag", function() { var Tag = require(local("../../lib/tag")); var Obj = require(local("../../lib/object")); var Oid = require(local("../../lib/oid")); + var Reference = require(local("../../lib/reference")); + var Promise = require("nodegit-promise"); var reposPath = local("../repos/workdir/.git"); var tagName = "annotated-tag"; @@ -15,8 +17,8 @@ describe("Tag", function() { var commitPointedTo = "32789a79e71fbc9e04d3eff7425e1771eb595150"; var tagMessage = "This is an annotated tag\n"; - function testTag(tag) { - assert.equal(tag.name(), tagName); + function testTag(tag, name) { + assert.equal(tag.name(), name || tagName); assert.equal(tag.targetType(), Obj.TYPE.COMMIT); assert.equal(tag.message(), tagMessage); @@ -75,4 +77,71 @@ describe("Tag", function() { assert.equal(tagNames.length, 1); }); }); + + it("can create a new annotated tag in a repo and delete it", function() { + var oid = Oid.fromString(commitPointedTo); + var name = "created-annotated-tag"; + var repository = this.repository; + + return repository.createTag(oid, name, tagMessage) + .then(function(tag) { + testTag(tag, name); + }) + .then(function() { + return repository.createTag(oid, name, tagMessage); + }) + .then(function() { + return Promise.reject(new Error("should not be able to create the '" + + name + "' tag twice")); + }, function() { + return Promise.resolve(); + }) + .then(function() { + return repository.deleteTagByName(name); + }) + .then(function() { + return Reference.lookup(repository, "refs/tags/" + name); + }) + .then(function() { + return Promise.reject(new Error("the tag '" + name + + "' should not exist")); + }, function() { + return Promise.resolve(); + }); + }); + + it("can create a new lightweight tag in a repo and delete it", function() { + var oid = Oid.fromString(commitPointedTo); + var name = "created-lightweight-tag"; + var repository = this.repository; + + return repository.createLightweightTag(oid, name) + .then(function(reference) { + return reference.target(); + }) + .then(function(refOid) { + assert.equal(refOid.toString(), oid.toString()); + }) + .then(function() { + return repository.createLightweightTag(oid, name); + }) + .then(function() { + return Promise.reject(new Error("should not be able to create the '" + + name + "' tag twice")); + }, function() { + return Promise.resolve(); + }) + .then(function() { + return repository.deleteTagByName(name); + }) + .then(function() { + return Reference.lookup(repository, "refs/tags/" + name); + }) + .then(function() { + return Promise.reject(new Error("the tag '" + name + + "' should not exist")); + }, function() { + return Promise.resolve(); + }); + }); });