UNPKG

@readme/nodegit

Version:

Node.js libgit2 asynchronous native bindings

176 lines (150 loc) 3.96 kB
var path = require("path"); var events = require("events"); var NodeGit = require("../"); var Diff = NodeGit.Diff; var LookupWrapper = NodeGit.Utils.lookupWrapper; var Tree = NodeGit.Tree; var Treebuilder = NodeGit.Treebuilder; /** * Retrieves the tree pointed to by the oid * @async * @param {Repository} repo The repo that the tree lives in * @param {String|Oid|Tree} id The tree to lookup * @return {Tree} */ Tree.lookup = LookupWrapper(Tree); /** * Make builder. This is helpful for modifying trees. * @return {Treebuilder} */ Tree.prototype.builder = function() { var builder = Treebuilder.create(this); builder.root = builder; builder.repo = this.repo; return builder; }; /** * Diff two trees * @async * @param {Tree} tree to diff against * @return {Diff} */ Tree.prototype.diff = function(tree) { return this.diffWithOptions(tree, null); }; /** * Diff two trees with options * @async * @param {Tree} tree to diff against * @param {Object} options * @return {Diff} */ Tree.prototype.diffWithOptions = function(tree, options) { return Diff.treeToTree(this.repo, tree, this, options); }; /** * Return an array of the entries in this tree (excluding its children). * @return {Array<TreeEntry>} an array of TreeEntrys */ Tree.prototype.entries = function() { var size = this.entryCount(); var result = []; for (var i = 0; i < size; i++) { result.push(this.entryByIndex(i)); } return result; }; /** * Get an entry at the ith position. * * @param {Number} i * @return {TreeEntry} */ Tree.prototype.entryByIndex = function(i) { var entry = this._entryByIndex(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 = this._entryByName(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` * @async * @param {String} filePath * @return {TreeEntry} */ Tree.prototype.getEntry = function(filePath) { var tree = this; return this.entryByPath(filePath).then(function(entry) { entry.parent = tree; entry.dirtoparent = path.dirname(filePath); return entry; }); }; /** * Return the path of this tree, like `/lib/foo/bar` * @return {String} */ Tree.prototype.path = function(blobsOnly) { return this.entry ? this.entry.path() : ""; }; /** * Recursively walk the tree in breadth-first order. Fires an event for each * entry. * * @fires EventEmitter#entry Tree * @fires EventEmitter#end Array<Tree> * @fires EventEmitter#error Error * * @param {Boolean} [blobsOnly = true] True to emit only blob & blob executable * entries. * * @return {EventEmitter} */ Tree.prototype.walk = function(blobsOnly) { blobsOnly = typeof blobsOnly === "boolean" ? blobsOnly : true; var self = this; var event = new events.EventEmitter(); var total = 1; var entries = new Set(); var finalEntires = []; // 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 event.emit("error", error); } tree.entries().forEach(function (entry, entryIndex) { if (!blobsOnly || entry.isFile() && !entries.has(entry)) { event.emit("entry", entry); entries.add(entry); // Node 0.12 doesn't support either [v for (v of entries)] nor // Array.from so we'll just maintain our own list. finalEntires.push(entry); } if (entry.isTree()) { total++; entry.getTree() .then(result => bfs(null, result), bfs); } }); if (total === 0) { event.emit("end", finalEntires); } } event.start = function() { bfs(null, self); }; return event; };