var events = require("events");
var NodeGit = require("../");
var Commit = NodeGit.Commit;
var LookupWrapper = NodeGit.Utils.lookupWrapper;
/**
* Retrieves the commit pointed to by the oid
* @async
* @param {Repository} repo The repo that the commit lives in
* @param {String|Oid|Commit} id The commit to lookup
* @return {Commit}
*/
Commit.lookup = LookupWrapper(Commit);
/**
* Retrieve the SHA.
* @return {String}
*/
Commit.prototype.sha = function() {
return this.id().toString();
};
/**
* Retrieve the commit time as a unix timestamp.
* @return {Number}
*/
Commit.prototype.timeMs = function() {
return this.time() * 1000;
};
/**
* Retrieve the commit time as a Date object.
* @return {Date}
*/
Commit.prototype.date = function() {
return new Date(this.timeMs());
};
/**
* Get the tree associated with this commit.
*
* @async
* @return {Tree}
*/
Commit.prototype.getTree = function(callback) {
return this.repo.getTree(this.treeId(), callback);
};
/**
* Retrieve the entry represented by path for this commit.
* Path must be relative to repository root.
*
* @async
* @param {String} path
* @return {TreeEntry}
*/
Commit.prototype.getEntry = function(path, callback) {
return this.getTree().then(function(tree) {
return tree.getEntry(path).then(function(entry) {
if (typeof callback === "function") {
callback(null, entry);
}
return entry;
});
}, callback);
};
/**
* Walk the history from this commit backwards.
*
* An EventEmitter is returned that will emit a "commit" event for each
* commit in the history, and one "end" event when the walk is completed.
* Don't forget to call `start()` on the returned event.
*
* @fires EventEmitter#commit Commit
* @fires EventEmitter#end Array
* @fires EventEmitter#error Error
*
* @return {EventEmitter}
* @start start()
*/
Commit.prototype.history = function() {
var event = new events.EventEmitter();
var oid = this.id();
var revwalk = this.repo.createRevWalk();
revwalk.sorting.apply(revwalk, arguments);
var commits = [];
event.start = function() {
revwalk.walk(oid, function commitRevWalk(error, commit) {
if (error) {
if (error.errno === NodeGit.Error.CODE.ITEROVER) {
event.emit("end", commits);
return;
} else {
return event.emit("error", error);
}
}
event.emit("commit", commit);
commits.push(commit);
});
};
return event;
};
/**
* Retrieve the commit's parents as commit objects.
*
* @async
* @param {number} limit Optional amount of parents to return.
* @param {Function} callback
* @return {Array} array of commits
*/
Commit.prototype.getParents = function(limit, callback) {
var parents = [];
// Shift arguments.
if (typeof limit === "function") {
callback = limit;
}
// If no limit was set, default to the maximum parents.
limit = typeof limit === "number" ? limit : this.parentcount();
limit = Math.min(limit, this.parentcount());
for (var i = 0; i < limit; i++) {
var oid = this.parentId(i);
var parent = this.repo.getCommit(oid);
parents.push(parent);
}
// Wait for all parents to complete, before returning.
return Promise.all(parents).then(function(parents) {
if (typeof callback === "function") {
callback(null, parents);
}
return parents;
}, callback);
};
/**
* Retrieve the commit"s parent shas.
*
* @param {Function} callback
* @return {Array} array of oids
*/
Commit.prototype.parents = function() {
var result = [];
for (var i = 0; i < this.parentcount(); i++) {
result.push(this.parentId(i));
}
return result;
};
/**
* Generate an array of diff trees showing changes between this commit
* and its parent(s).
*
* @async
* @param {Function} callback
* @return {Array} an array of diffs
*/
Commit.prototype.getDiff = function(callback) {
return this.getDiffWithOptions(null, callback);
};
/**
* Generate an array of diff trees showing changes between this commit
* and its parent(s).
*
* @async
* @param {Object} options
* @param {Function} callback
* @return {Array} an array of diffs
*/
Commit.prototype.getDiffWithOptions = function(options, callback) {
var commit = this;
return commit.getTree().then(function(thisTree) {
return commit.getParents().then(function(parents) {
var diffs;
if (parents.length) {
diffs = parents.map(function(parent) {
return parent.getTree().then(function(parentTree) {
return thisTree.diffWithOptions(parentTree, options);
});
});
} else {
diffs = [thisTree.diffWithOptions(null, options)];
}
return Promise.all(diffs);
});
}).then(function(diffs) {
if (typeof callback === "function") {
callback(null, diffs);
}
return diffs;
}, callback);
};
/**
* Amend a commit
* @async
* @param {String} update_ref
* @param {Signature} author
* @param {Signature} committer
* @param {String} message_encoding
* @param {String} message
* @param {Tree|Oid} tree
* @param {Oid} callback
*/
var amend = Commit.prototype.amend;
Commit.prototype.amend = function (
updateRef, author, committer, message_encoding, message, tree, callback) {
var repo = this.repo;
var _this = this;
var treePromise;
if (tree instanceof NodeGit.Oid){
treePromise = repo.getTree(tree);
} else {
treePromise = Promise.resolve(tree);
}
return treePromise
.then(function(treeObject){
return amend.call(_this,
updateRef,
author,
committer,
message_encoding,
message,
treeObject
);
});
};
/**
* The sha of this commit
* @return {String}
*/
Commit.prototype.toString = function() {
return this.sha();
};