From ab4ba2ca4ca07cb56927da8593d258043a49be48 Mon Sep 17 00:00:00 2001 From: Daniel Hengeveld Date: Mon, 19 Oct 2015 15:15:42 +0200 Subject: [PATCH] .getPathStatus() --- spec/git-repository-async-spec.coffee | 42 ++++++++++++++++---------- src/git-repository-async.js | 43 +++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 15 deletions(-) diff --git a/spec/git-repository-async-spec.coffee b/spec/git-repository-async-spec.coffee index 7de2a0b01..2972db635 100644 --- a/spec/git-repository-async-spec.coffee +++ b/spec/git-repository-async-spec.coffee @@ -1,5 +1,6 @@ temp = require 'temp' GitRepositoryAsync = require '../src/git-repository-async' +Git = require 'nodegit' fs = require 'fs-plus' os = require 'os' path = require 'path' @@ -18,7 +19,7 @@ copyRepository = -> openFixture = (fixture)-> GitRepositoryAsync.open(path.join(__dirname, 'fixtures', 'git', fixture)) -fdescribe "GitRepositoryAsync", -> +describe "GitRepositoryAsync", -> repo = null # beforeEach -> @@ -154,6 +155,8 @@ fdescribe "GitRepositoryAsync", -> describe ".checkoutHead(path)", -> + # XXX this is failing sporadically with various errors around not finding the + # repo / files in the repo [filePath] = [] beforeEach -> @@ -175,16 +178,17 @@ fdescribe "GitRepositoryAsync", -> runs -> expect(onSuccess.mostRecentCall.args[0]).toBeTruthy() - # Don't need to assert that this succeded because waitsForPromise will - # fail if it was rejected. + # Don't need to assert that this succeded because waitsForPromise should + # fail if it was rejected.. waitsForPromise -> repo.checkoutHead(filePath) - onSuccess = jasmine.createSpy('onSuccess') - waitsForPromise -> - repo.isPathModified(filePath).then(onSuccess) runs -> - expect(onSuccess.mostRecentCall.args[0]).toBeFalsy() + onSuccess = jasmine.createSpy('onSuccess') + waitsForPromise -> + repo.isPathModified(filePath).then(onSuccess) + runs -> + expect(onSuccess.mostRecentCall.args[0]).toBeFalsy() it "restores the contents of the path to the original text", -> fs.writeFileSync(filePath, 'ch ch changes') @@ -243,25 +247,33 @@ fdescribe "GitRepositoryAsync", -> repo.destroy() expect(-> repo.getShortHead()).toThrow() - xdescribe ".getPathStatus(path)", -> + describe ".getPathStatus(path)", -> [filePath] = [] beforeEach -> workingDirectory = copyRepository() - repo = new GitRepository(workingDirectory) + repo = GitRepositoryAsync.open(workingDirectory) filePath = path.join(workingDirectory, 'file.txt') it "trigger a status-changed event when the new status differs from the last cached one", -> statusHandler = jasmine.createSpy("statusHandler") repo.onDidChangeStatus statusHandler fs.writeFileSync(filePath, '') - status = repo.getPathStatus(filePath) - expect(statusHandler.callCount).toBe 1 - expect(statusHandler.argsForCall[0][0]).toEqual {path: filePath, pathStatus: status} - fs.writeFileSync(filePath, 'abc') - status = repo.getPathStatus(filePath) - expect(statusHandler.callCount).toBe 1 + waitsForPromise -> + repo.getPathStatus(filePath) + + runs -> + expect(statusHandler.callCount).toBe 1 + status = Git.Status.STATUS.WT_MODIFIED + expect(statusHandler.argsForCall[0][0]).toEqual {path: filePath, pathStatus: status} + fs.writeFileSync(filePath, 'abc') + + waitsForPromise -> + status = repo.getPathStatus(filePath) + + runs -> + expect(statusHandler.callCount).toBe 1 xdescribe ".getDirectoryStatus(path)", -> [directoryPath, filePath] = [] diff --git a/src/git-repository-async.js b/src/git-repository-async.js index 7d7aab570..d99948afc 100644 --- a/src/git-repository-async.js +++ b/src/git-repository-async.js @@ -2,6 +2,7 @@ const Git = require('nodegit') const path = require('path') +const {Emitter, Disposable, CompositeDisposable} = require('event-kit') // GitUtils is temporarily used for ::relativize only, because I don't want // to port it just yet. TODO: remove @@ -15,10 +16,17 @@ module.exports = class GitRepositoryAsync { constructor (path) { this.repo = null + this.emitter = new Emitter() + this.subscriptions = new CompositeDisposable() + this.pathStatusCache = {} this._gitUtilsRepo = GitUtils.open(path) // TODO remove after porting ::relativize this.repoPromise = Git.Repository.open(path) } + destroy () { + this.subscriptions.dispose() + } + getPath () { return this.repoPromise.then((repo) => { return Promise.resolve(repo.path().replace(/\/$/, '')) @@ -38,6 +46,7 @@ module.exports = class GitRepositoryAsync { basePath = repo.workdir() return repo.getStatus() }).then((statuses) => { + console.log('statuses', statuses) return statuses.filter(function (status) { return _path === path.join(basePath, status.path()) }) @@ -70,4 +79,38 @@ module.exports = class GitRepositoryAsync { Git.Checkout.head(repo, checkoutOptions) }) } + + // Returns a Promise that resolves to the status bit of a given path if it has + // one, otherwise 'current'. + getPathStatus (_path) { + var relativePath = this._gitUtilsRepo.relativize(_path) + return this.repoPromise.then((repo) => { + return this._filterStatusesByPath(_path) + }).then((statuses) => { + var cachedStatus = this.pathStatusCache[relativePath] || 0 + var status = statuses[0] ? statuses[0].statusBit() : Git.Status.STATUS.CURRENT + console.log('cachedStatus', cachedStatus, 'status', status) + if (status != cachedStatus) { + this.emitter.emit('did-change-status', {path: _path, pathStatus: status}) + } + this.pathStatusCache[relativePath] = status + return Promise.resolve(status) + }) + } + + // Event subscription + // ================== + + onDidChangeStatus (callback) { + return this.emitter.on('did-change-status', callback) + } + + onDidChangeStatuses (callback) { + return this.emitter.on('did-change-statuses', callback) + } + + onDidDestroy (callback) { + return this.emitter.on('did-destroy', callback) + } + }