var git = require('../'),
Tree = git.Tree,
events = require('events'),
path = require('path');
var oldEntryByIndex = Tree.prototype.entryByIndex,
oldEntryByName = Tree.prototype.entryByName,
oldGetEntry = Tree.prototype.getEntry;
/**
* Diff two trees
* @param {Tree} tree to diff against
* @param {Function} callback
* @return {DiffList}
*/
Tree.prototype.diff = function(that, callback) {
this.diffTree(this.repo, that, null, callback);
};
/**
* Get an entry at the ith position.
*
* @param {Number} i
* @return {TreeEntry}
*/
Tree.prototype.entryByIndex = function(i) {
var entry = oldEntryByIndex.call(this, i);
entry.parent = this;
return entry;
};
/**
* Get an entry by name; if the tree is a directory, the name is the filename.
*
* @param {String} name
* @return {TreeEntry}
*/
Tree.prototype.entryByName = function(name) {
var entry = oldEntryByName.call(this, name);
entry.parent = this;
return entry;
};
/**
* Get an entry at a path. Unlike by name, this takes a fully
* qualified path, like `/foo/bar/baz.javascript`
*
* @param {String} path
* @return {TreeEntry}
*/
Tree.prototype.getEntry = function(path, callback) {
// FIXME: this method ought to implement the recursion directly, rather than
// rely on oldGetEntry, in order to ensure that `parent` pointers are direct.
var self = this;
oldGetEntry.call(this, path, function(error, entry) {
if (error) return callback(error);
entry.parent = self;
entry.path = function() { return path };
callback(null, entry);
});
};
/**
* Return an array of the entries in this tree (excluding its children).
* @return {[TreeEntry]} an array of TreeEntrys
*/
Tree.prototype.entries = function() {
var size = this.size(),
result = [];
for (var i = 0; i < size; i++) {
result.push(this.entryByIndex(i));
}
return result;
};
/**
* Recursively walk the tree in breadth-first order. Fires an event for each entry.
*
* @fires Tree#entry
* @fires Tree#end
*
* @param {Boolean} [blobsOnly = true] True to emit only blob & blob executable entries.
*
* @return {EventEmitter}
*/
Tree.prototype.walk = function(blobsOnly) {
if (typeof blobsOnly == 'undefined') blobsOnly = true;
var self = this,
event = new events.EventEmitter(),
entries = [],
errors = [];
var total = 1;
// This looks like a DFS, but it is a BFS because of implicit queueing in
// the recursive call to `entry.getTree(bfs)`
function bfs(error, tree) {
total--;
if (error) return errors.push(error);
tree.entries().forEach(function (entry) {
if (!blobsOnly || entry.isFile()) {
event.emit('entry', entry);
entries.push(entry);
}
if (entry.isTree()) {
total++;
entry.getTree(bfs);
}
});
if (total === 0)
event.emit('end', errors.length ? errors : null, entries);
}
event.start = function() {
bfs(null, self);
};
return event;
};
/**
* Return the path of this tree, like `/lib/foo/bar`
* @return {String}
*/
Tree.prototype.path = function(blobsOnly) {
return this.entry ? this.entry.path() : '';
};
/**
* Make builder. This is helpful for modifying trees.
* @return {TreeBuilder}
*/
var oldBuilder = Tree.prototype.builder;
Tree.prototype.builder = function() {
var builder = oldBuilder.call(this);
builder.root = builder;
builder.repo = this.repo;
return builder;
};