From 8da08724ad5e54ae19a15a359b62a070f3653b3e Mon Sep 17 00:00:00 2001 From: joshaber Date: Wed, 2 Dec 2015 23:51:33 -0500 Subject: [PATCH] Added getDiffStats. --- spec/git-repository-async-spec.js | 17 ++++++++++++++ src/git-repository-async.js | 38 +++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/spec/git-repository-async-spec.js b/spec/git-repository-async-spec.js index 1b45d12f6..6aa2e6f81 100644 --- a/spec/git-repository-async-spec.js +++ b/spec/git-repository-async-spec.js @@ -436,4 +436,21 @@ describe('GitRepositoryAsync', () => { expect(behind).toBe(0) }) }) + + describe('.getDiffStats(path)', () => { + let workingDirectory + beforeEach(() => { + workingDirectory = copyRepository() + repo = GitRepositoryAsync.open(workingDirectory) + }) + + it('returns the diff stat', async () => { + const filePath = path.join(workingDirectory, 'a.txt') + fs.writeFileSync(filePath, 'change') + + const {added, deleted} = await repo.getDiffStats('a.txt') + expect(added).toBe(1) + expect(deleted).toBe(0) + }) + }) }) diff --git a/src/git-repository-async.js b/src/git-repository-async.js index 91954fab6..131b1b51c 100644 --- a/src/git-repository-async.js +++ b/src/git-repository-async.js @@ -391,6 +391,44 @@ export default class GitRepositoryAsync { return (statusBit & deletedStatusFlags) > 0 } + // Retrieving Diffs + // ================ + // Public: Retrieves the number of lines added and removed to a path. + // + // This compares the working directory contents of the path to the `HEAD` + // version. + // + // * `path` The {String} path to check. + // + // Returns a {Promise} which resolves to an {Object} with the following keys: + // * `added` The {Number} of added lines. + // * `deleted` The {Number} of deleted lines. + getDiffStats (_path) { + return this.repoPromise + .then(repo => Promise.all([repo, repo.getHeadCommit()])) + .then(([repo, headCommit]) => Promise.all([repo, headCommit.getTree()])) + .then(([repo, tree]) => { + const options = new Git.DiffOptions() + options.pathspec = _path + return Git.Diff.treeToWorkdir(repo, tree, options) + }) + .then(diff => diff.patches()) // :: Array + .then(patches => Promise.all(patches.map(p => p.hunks()))) // :: Array> + .then(hunks => Promise.all(_.flatten(hunks).map(h => h.lines()))) // :: Array> + .then(lines => { + const stats = {added: 0, deleted: 0} + for (const line of _.flatten(lines)) { + const origin = line.origin() + if (origin === Git.Diff.LINE.ADDITION) { + stats.added++ + } else if (origin === Git.Diff.LINE.DELETION) { + stats.deleted++ + } + } + return stats + }) + } + // Checking Out // ============