diff --git a/lib/controllers/git-panel-controller.js b/lib/controllers/git-panel-controller.js
index 424d71aba1..40c654ee61 100644
--- a/lib/controllers/git-panel-controller.js
+++ b/lib/controllers/git-panel-controller.js
@@ -15,6 +15,7 @@ export default class GitPanelController {
this.pull = this.pull.bind(this)
this.fetch = this.fetch.bind(this)
this.commit = this.commit.bind(this)
+ this.setAmending = this.setAmending.bind(this)
this.checkout = this.checkout.bind(this)
this.abortMerge = this.abortMerge.bind(this)
this.switchRepository(props.repository)
@@ -47,7 +48,9 @@ export default class GitPanelController {
stageFiles={this.stageFiles}
unstageFiles={this.unstageFiles}
commit={this.commit}
+ setAmending={this.setAmending}
isMerging={this.isMerging}
+ isAmending={this.isAmending}
abortMerge={this.abortMerge}
push={this.push}
pull={this.pull}
@@ -87,7 +90,7 @@ export default class GitPanelController {
async _refreshModelData (repository) {
if (repository) {
this.unstagedChanges = await repository.getUnstagedChanges()
- this.stagedChanges = await repository.getStagedChanges()
+ await this._refreshStagedChanges(repository)
this.mergeConflicts = await repository.getMergeConflicts()
this.lastCommit = await repository.getLastCommit()
this.isMerging = await repository.isMerging()
@@ -111,6 +114,14 @@ export default class GitPanelController {
return etch.update(this)
}
+ async _refreshStagedChanges (repository) {
+ if (this.isAmending) {
+ this.stagedChanges = await repository.getStagedChangesSinceParentCommit()
+ } else {
+ this.stagedChanges = await repository.getStagedChanges()
+ }
+ }
+
unstageFilePatch (filePatch) {
return this.repository.applyPatchToIndex(filePatch.getUnstagePatch())
}
@@ -132,7 +143,11 @@ export default class GitPanelController {
}
unstageFiles (filePaths) {
- return this.repository.unstageFiles(filePaths)
+ if (this.isAmending) {
+ return this.repository.stageFilesFromParentCommit(filePaths)
+ } else {
+ return this.repository.unstageFiles(filePaths)
+ }
}
push () {
@@ -155,8 +170,16 @@ export default class GitPanelController {
return this.stagedChanges.length === 0 && this.unstagedChanges.length === 0
}
- commit (message, options) {
- return this.repository.commit(message, options)
+ async commit (message, options) {
+ await this.repository.commit(message, options)
+ this.setAmending(false)
+ }
+
+ async setAmending (isAmending) {
+ if (this.props.didChangeAmending) this.props.didChangeAmending()
+ this.isAmending = isAmending
+ await this._refreshStagedChanges(this.repository)
+ return etch.update(this)
}
abortMerge () {
diff --git a/lib/git-shell-out-strategy.js b/lib/git-shell-out-strategy.js
index 9811afa976..b042f7f5eb 100644
--- a/lib/git-shell-out-strategy.js
+++ b/lib/git-shell-out-strategy.js
@@ -45,9 +45,9 @@ export default class GitShellOutStrategy {
return this.exec(args)
}
- unstageFiles (paths) {
+ unstageFiles (paths, commit = 'HEAD') {
if (paths.length === 0) return
- const args = ['reset', '--'].concat(paths)
+ const args = ['reset', commit, '--' ].concat(paths)
return this.exec(args)
}
@@ -98,6 +98,7 @@ export default class GitShellOutStrategy {
async diff (options = {}) {
let args = ['diff', '--no-prefix', '--no-renames', '--diff-filter=u']
if (options.staged) args.push('--staged')
+ if (options.baseCommit) args.push(options.baseCommit)
let output = await this.exec(args)
let rawDiffs = []
diff --git a/lib/github-package.js b/lib/github-package.js
index 4836e77b10..01fdbf7846 100644
--- a/lib/github-package.js
+++ b/lib/github-package.js
@@ -28,7 +28,8 @@ export default class GithubPackage {
commandRegistry,
notificationManager,
didSelectFilePatch: this.didSelectFilePatch.bind(this),
- didSelectMergeConflictFile: this.didSelectMergeConflictFile.bind(this)
+ didSelectMergeConflictFile: this.didSelectMergeConflictFile.bind(this),
+ didChangeAmending: this.didChangeAmending.bind(this)
})
this.changedFilesCountController = new ChangedFilesCountController({
repository: null, didClick: this.toggleGitPanel.bind(this)
@@ -97,6 +98,13 @@ export default class GithubPackage {
}
}
+ didChangeAmending () {
+ if (this.filePatchController && this.filePatchController.props.stagingStatus === 'staged') {
+ this.filePatchController.destroy()
+ this.filePatchController = null
+ }
+ }
+
toggleGitPanel () {
if (this.workspaceGitPanel) {
this.workspaceGitPanel.destroy()
diff --git a/lib/helpers.js b/lib/helpers.js
index fc5bf690e5..7f6baa9921 100644
--- a/lib/helpers.js
+++ b/lib/helpers.js
@@ -38,6 +38,10 @@ export function fsStat (absoluteFilePath) {
})
}
+export function shortenSha (sha) {
+ return sha.slice(0, 8)
+}
+
export const classNameForStatus = {
added: 'added',
deleted: 'removed',
diff --git a/lib/models/repository.js b/lib/models/repository.js
index d83ac36080..6d6bb32974 100644
--- a/lib/models/repository.js
+++ b/lib/models/repository.js
@@ -45,6 +45,7 @@ export default class Repository {
this.workingDirectory = workingDirectory
this.emitter = new Emitter()
this.stagedFilePatchesByPath = new Map()
+ this.stagedFilePatchesSinceParentCommitByPath = new Map()
this.unstagedFilePatchesByPath = new Map()
this.mergeConflictsByPath = new Map()
this.git = gitStrategy
@@ -76,86 +77,94 @@ export default class Repository {
async refresh () {
if (global.PRINT_GIT_TIMES) console.time('refresh')
- await this.refreshStagedChanges()
- await this.refreshUnstagedChanges()
- await this.refreshMergeConflicts()
+ this.stagedChangesPromise = this.fetchStagedChanges()
+ this.stagedChangesSinceParentCommitPromise = this.fetchStagedChangesSinceParentCommit()
+ this.unstagedChangesPromise = this.fetchUnstagedChanges()
+ this.mergeConflictsPromise = this.fetchMergeConflicts()
+ await Promise.all([
+ this.stagedChangesPromise,
+ this.stagedChangesSinceParentCommitPromise,
+ this.unstagedChangesPromise,
+ this.mergeConflictsPromise
+ ])
if (global.PRINT_GIT_TIMES) console.timeEnd('refresh')
this.didUpdate()
}
getUnstagedChanges () {
- return this.unstagedChangesPromise || this.refreshUnstagedChanges()
+ if (!this.unstagedChangesPromise) {
+ this.unstagedChangesPromise = this.fetchUnstagedChanges()
+ }
+ return this.unstagedChangesPromise
}
getStagedChanges () {
- return this.stagedChangesPromise || this.refreshStagedChanges()
+ if (!this.stagedChangesPromise) {
+ this.stagedChangesPromise = this.fetchStagedChanges()
+ }
+ return this.stagedChangesPromise
}
- getMergeConflicts () {
- return this.mergeConflictsPromise || this.refreshMergeConflicts()
+ getStagedChangesSinceParentCommit () {
+ if (!this.stagedChangesSinceParentCommitPromise) {
+ this.stagedChangesSinceParentCommitPromise = this.fetchStagedChangesSinceParentCommit()
+ }
+ return this.stagedChangesSinceParentCommitPromise
}
- refreshUnstagedChanges () {
- this.unstagedChangesPromise = this.fetchUnstagedChanges()
- return this.unstagedChangesPromise
+ getMergeConflicts () {
+ if (!this.mergeConflictsPromise) {
+ this.mergeConflictsPromise = this.fetchMergeConflicts()
+ }
+ return this.mergeConflictsPromise
}
- refreshStagedChanges () {
- this.stagedChangesPromise = this.fetchStagedChanges()
- return this.stagedChangesPromise
+ async fetchUnstagedChanges () {
+ const rawDiffs = await this.git.diff()
+ return this.updateFilePatches(this.unstagedFilePatchesByPath, rawDiffs)
}
- refreshMergeConflicts () {
- this.mergeConflictsPromise = this.fetchMergeConflicts()
- return this.mergeConflictsPromise
+ async fetchStagedChanges () {
+ const rawDiffs = await this.git.diff({staged: true})
+ return this.updateFilePatches(this.stagedFilePatchesByPath, rawDiffs)
}
- async fetchUnstagedChanges () {
- const rawDiffs = await this.git.diff()
- const validFilePatches = new Set()
- for (let newPatch of this.buildFilePatchesFromRawDiffs(rawDiffs)) {
- const path = newPatch.getPath()
- const existingPatch = this.unstagedFilePatchesByPath.get(path)
- if (existingPatch == null) {
- this.unstagedFilePatchesByPath.set(path, newPatch)
+ async fetchStagedChangesSinceParentCommit () {
+ try {
+ const rawDiffs = await this.git.diff({staged: true, baseCommit: 'HEAD~'})
+ return this.updateFilePatches(this.stagedFilePatchesSinceParentCommitByPath, rawDiffs)
+ } catch (e) {
+ if (e.message.includes(`ambiguous argument 'HEAD~'`)) {
+ return []
} else {
- existingPatch.update(newPatch)
- }
- validFilePatches.add(path)
- }
-
- for (let [path, patch] of this.unstagedFilePatchesByPath) {
- if (!validFilePatches.has(path)) {
- this.unstagedFilePatchesByPath.delete(path)
- patch.destroy()
+ throw e
}
}
- return Array.from(this.unstagedFilePatchesByPath.values())
- .sort((a, b) => a.getPath().localeCompare(b.getPath()))
}
- async fetchStagedChanges () {
- const rawDiffs = await this.git.diff({staged: true})
+ updateFilePatches (patchesByPath, rawDiffs) {
+ const filePatches = this.buildFilePatchesFromRawDiffs(rawDiffs)
+
const validFilePatches = new Set()
- for (let newPatch of this.buildFilePatchesFromRawDiffs(rawDiffs)) {
+ for (let newPatch of filePatches) {
const path = newPatch.getPath()
- const existingPatch = this.stagedFilePatchesByPath.get(path)
+ const existingPatch = patchesByPath.get(path)
if (existingPatch == null) {
- this.stagedFilePatchesByPath.set(path, newPatch)
+ patchesByPath.set(path, newPatch)
} else {
existingPatch.update(newPatch)
}
validFilePatches.add(path)
}
- for (let [path, patch] of this.stagedFilePatchesByPath) {
+ for (let [path, patch] of patchesByPath) {
if (!validFilePatches.has(path)) {
- this.stagedFilePatchesByPath.delete(path)
+ patchesByPath.delete(path)
patch.destroy()
}
}
- return Array.from(this.stagedFilePatchesByPath.values())
- .sort((a, b) => a.getPath().localeCompare(b.getPath()))
+
+ return Array.from(patchesByPath.values()).sort((a, b) => a.getPath().localeCompare(b.getPath()))
}
buildFilePatchesFromRawDiffs (rawDiffs) {
@@ -228,6 +237,11 @@ export default class Repository {
await this.refresh()
}
+ async stageFilesFromParentCommit (paths) {
+ await this.git.unstageFiles(paths, 'HEAD~')
+ await this.refresh()
+ }
+
async applyPatchToIndex (filePatch) {
const patchStr = filePatch.getHeaderString() + filePatch.toString()
await this.git.applyPatchToIndex(patchStr)
@@ -268,7 +282,8 @@ export default class Repository {
async commit (message, options) {
await this.git.commit(this.stripCommitComments(message), options)
- this.refreshStagedChanges()
+ this.stagedChangesPromise = null
+ this.stagedChangesSinceParentCommitPromise = null
this.didUpdate()
}
diff --git a/lib/views/commit-view.js b/lib/views/commit-view.js
index 911a18b732..9f3b1b2788 100644
--- a/lib/views/commit-view.js
+++ b/lib/views/commit-view.js
@@ -3,6 +3,7 @@
import {CompositeDisposable} from 'atom'
import etch from 'etch'
+import {shortenSha} from '../helpers'
export default class CommitView {
constructor (props) {
@@ -64,7 +65,7 @@ export default class CommitView {
+ disabled={!this.isCommitButtonEnabled()}>{this.commitButtonText()}
0}
mergeConflictsExist={this.props.mergeConflicts.length > 0}
commit={this.props.commit}
+ setAmending={this.props.setAmending}
disableCommitButton={this}
abortMerge={this.props.abortMerge}
branchName={this.props.branchName}
@@ -67,6 +70,7 @@ export default class GitPanelView {
maximumCharacterLimit={72}
message={this.props.mergeMessage}
isMerging={this.props.isMerging}
+ isAmending={this.props.isAmending}
lastCommit={this.props.lastCommit}
/>
diff --git a/lib/views/staging-view.js b/lib/views/staging-view.js
index 2699ee88f3..2bda299b7c 100644
--- a/lib/views/staging-view.js
+++ b/lib/views/staging-view.js
@@ -10,6 +10,7 @@ import MergeConflict from '../models/merge-conflict'
import FilePatchListItemView from './file-patch-list-item-view'
import MergeConflictListItemView from './merge-conflict-list-item-view'
import MultiListCollection from '../multi-list-collection'
+import {shortenSha} from '../helpers'
export const ListTypes = {
STAGED: Symbol('LIST_STAGED'),
@@ -220,7 +221,14 @@ export default class StagingView {
- Staged Changes
+
+ Staged Changes
+ {
+ this.props.isAmending ?
+ ` (amending ${shortenSha(this.props.lastCommit.sha)})` :
+ ''
+ }
+
this.selectList(ListTypes.STAGED, {suppressCallback: true})}
diff --git a/test/controllers/changed-files-count-controller.test.js b/test/controllers/changed-files-count-controller.test.js
index baf94e7829..8a6f29005d 100644
--- a/test/controllers/changed-files-count-controller.test.js
+++ b/test/controllers/changed-files-count-controller.test.js
@@ -22,11 +22,13 @@ describe('ChangedFilesCountController', () => {
fs.writeFileSync(path.join(workdirPath, 'a.txt'), 'a change\n')
fs.unlinkSync(path.join(workdirPath, 'b.txt'))
- const [patchToStage] = await repository.refreshUnstagedChanges()
+ repository.refresh()
+
+ const [patchToStage] = await repository.getUnstagedChanges()
await repository.applyPatchToIndex(patchToStage)
await view.lastModelDataRefreshPromise
- assert.deepEqual(view.refs.changedFilesCount.props.stagedChanges, await repository.refreshStagedChanges())
- assert.deepEqual(view.refs.changedFilesCount.props.unstagedChanges, await repository.refreshUnstagedChanges())
+ assert.deepEqual(view.refs.changedFilesCount.props.stagedChanges, await repository.getStagedChanges())
+ assert.deepEqual(view.refs.changedFilesCount.props.unstagedChanges, await repository.getUnstagedChanges())
view.refs.changedFilesCount.props.didClick()
assert(didClick.calledOnce)
diff --git a/test/controllers/git-panel-controller.test.js b/test/controllers/git-panel-controller.test.js
index 12b09e0727..f340a3bea0 100644
--- a/test/controllers/git-panel-controller.test.js
+++ b/test/controllers/git-panel-controller.test.js
@@ -56,6 +56,27 @@ describe('GitPanelController', () => {
assert.equal(controller.refs.gitPanel.props.unstagedChanges, await repository2.getUnstagedChanges())
})
+ it('displays the staged changes since the parent commmit when amending', async function () {
+ const didChangeAmending = sinon.spy()
+ const workdirPath = await cloneRepository('multiple-commits')
+ const repository = await buildRepository(workdirPath)
+ const controller = new GitPanelController({workspace, commandRegistry, repository, didChangeAmending})
+ await controller.lastModelDataRefreshPromise
+ assert.deepEqual(controller.refs.gitPanel.props.stagedChanges, [])
+ assert.equal(didChangeAmending.callCount, 0)
+
+ await controller.setAmending(true)
+ assert.equal(didChangeAmending.callCount, 1)
+ assert.deepEqual(
+ controller.refs.gitPanel.props.stagedChanges,
+ await controller.repository.getStagedChangesSinceParentCommit()
+ )
+
+ await controller.commit('Delete most of the code', {amend: true})
+ await controller.lastModelDataRefreshPromise
+ assert(!controller.refs.gitPanel.props.isAmending)
+ })
+
describe('integration tests', () => {
it('can stage and unstage files and commit', async () => {
const workdirPath = await cloneRepository('three-files')
diff --git a/test/github-package.test.js b/test/github-package.test.js
index a9554fa7ec..83e13a6b9b 100644
--- a/test/github-package.test.js
+++ b/test/github-package.test.js
@@ -214,6 +214,24 @@ describe('GithubPackage', () => {
})
})
+ describe('when amend mode is toggled in the staging panel while viewing a staged change', () => {
+ it('closes the file patch pane item', async () => {
+ const workdirPath = await cloneRepository('three-files')
+ const repository = await buildRepository(workdirPath)
+
+ githubPackage.getActiveRepository = function () { return repository }
+ const hunk = new Hunk(1, 1, 1, 3, [])
+ const filePatch = new FilePatch('a.txt', 'a.txt', 'modified', [hunk])
+
+ githubPackage.gitPanelController.props.didSelectFilePatch(filePatch, 'staged')
+ assert.equal(workspace.getActivePaneItem(), githubPackage.filePatchController)
+
+ githubPackage.gitPanelController.props.didChangeAmending()
+ assert.isNull(githubPackage.filePatchController)
+ assert.isUndefined(workspace.getActivePaneItem())
+ })
+ })
+
describe('when the changed files label in the status bar is clicked', () => {
it('toggles the git panel', async () => {
const workdirPath = await cloneRepository('three-files')
diff --git a/test/models/repository.test.js b/test/models/repository.test.js
index c4ea3397b9..aaafa2556b 100644
--- a/test/models/repository.test.js
+++ b/test/models/repository.test.js
@@ -8,7 +8,7 @@ import sinon from 'sinon'
import {cloneRepository, buildRepository, assertDeepPropertyVals, setUpLocalAndRemoteRepositories, getHeadCommitOnRemote} from '../helpers'
describe('Repository', function () {
- describe('refreshing staged and unstaged changes', () => {
+ describe('getting staged and unstaged changes', () => {
it('returns a promise resolving to an array of FilePatch objects', async () => {
const workingDirPath = await cloneRepository('three-files')
fs.writeFileSync(path.join(workingDirPath, 'a.txt'), 'qux\nfoo\nbar\n', 'utf8')
@@ -17,7 +17,7 @@ describe('Repository', function () {
fs.writeFileSync(path.join(workingDirPath, 'e.txt'), 'qux', 'utf8')
const repo = await buildRepository(workingDirPath)
- const filePatches = await repo.refreshUnstagedChanges()
+ const filePatches = await repo.getUnstagedChanges()
assertDeepPropertyVals(filePatches, [
{
@@ -93,12 +93,14 @@ describe('Repository', function () {
fs.unlinkSync(path.join(workingDirPath, 'b.txt'))
fs.writeFileSync(path.join(workingDirPath, 'c.txt'), 'bar\nbaz')
fs.writeFileSync(path.join(workingDirPath, 'd.txt'), 'qux', 'utf8')
- const unstagedFilePatches1 = await repo.refreshUnstagedChanges()
+ await repo.refresh()
+ const unstagedFilePatches1 = await repo.getUnstagedChanges()
fs.writeFileSync(path.join(workingDirPath, 'a.txt'), 'baz\nfoo\nqux', 'utf8')
fs.writeFileSync(path.join(workingDirPath, 'c.txt'), 'baz')
fs.unlinkSync(path.join(workingDirPath, 'd.txt'))
- const unstagedFilePatches2 = await repo.refreshUnstagedChanges()
+ await repo.refresh()
+ const unstagedFilePatches2 = await repo.getUnstagedChanges()
assert.equal(unstagedFilePatches1.length, 4)
assert.equal(unstagedFilePatches2.length, 3)
@@ -110,11 +112,11 @@ describe('Repository', function () {
await repo.stageFiles([unstagedFilePatches2[0].getPath()])
await repo.stageFiles([unstagedFilePatches2[1].getPath()])
await repo.stageFiles([unstagedFilePatches2[2].getPath()])
- const stagedFilePatches1 = await repo.refreshStagedChanges()
+ const stagedFilePatches1 = await repo.getStagedChanges()
await repo.unstageFiles([stagedFilePatches1[2].getPath()])
- const stagedFilePatches2 = await repo.refreshStagedChanges()
- const unstagedFilePatches3 = await repo.refreshUnstagedChanges()
+ const stagedFilePatches2 = await repo.getStagedChanges()
+ const unstagedFilePatches3 = await repo.getUnstagedChanges()
assert.equal(stagedFilePatches1.length, 3)
assert.equal(stagedFilePatches2.length, 2)
@@ -169,7 +171,7 @@ describe('Repository', function () {
await repo.stageFiles([filePath1])
await repo.stageFiles([filePath2])
- assert.deepEqual(await repo.refreshStagedChanges(), patches)
+ assert.deepEqual(await repo.getStagedChanges(), patches)
assert.deepEqual(await repo.getUnstagedChanges(), [])
await repo.unstageFiles([filePath1])
@@ -193,6 +195,48 @@ describe('Repository', function () {
assert.deepEqual(await repo.getUnstagedChanges(), [patch])
assert.deepEqual(await repo.getStagedChanges(), [])
})
+
+ it('can unstage and retrieve staged changes relative to HEAD~', async () => {
+ const workingDirPath = await cloneRepository('multiple-commits')
+ const repo = await buildRepository(workingDirPath)
+ fs.writeFileSync(path.join(workingDirPath, 'file.txt'), 'three\nfour\n', 'utf8')
+ assertDeepPropertyVals(await repo.getStagedChangesSinceParentCommit(), [
+ {
+ oldPath: 'file.txt',
+ newPath: 'file.txt',
+ status: 'modified',
+ hunks: [
+ {
+ lines: [
+ {status: 'deleted', text: 'two', oldLineNumber: 1, newLineNumber: -1},
+ {status: 'added', text: 'three', oldLineNumber: -1, newLineNumber: 1},
+ ]
+ }
+ ]
+ }
+ ])
+
+ await repo.stageFiles(['file.txt'])
+ assertDeepPropertyVals(await repo.getStagedChangesSinceParentCommit(), [
+ {
+ oldPath: 'file.txt',
+ newPath: 'file.txt',
+ status: 'modified',
+ hunks: [
+ {
+ lines: [
+ {status: 'deleted', text: 'two', oldLineNumber: 1, newLineNumber: -1},
+ {status: 'added', text: 'three', oldLineNumber: -1, newLineNumber: 1},
+ {status: 'added', text: 'four', oldLineNumber: -1, newLineNumber: 2},
+ ]
+ }
+ ]
+ }
+ ])
+
+ await repo.stageFilesFromParentCommit(['file.txt'])
+ assert.deepEqual(await repo.getStagedChangesSinceParentCommit(), [])
+ })
})
describe('applyPatchToIndex', () => {
@@ -203,7 +247,8 @@ describe('Repository', function () {
const [unstagedPatch1] = (await repo.getUnstagedChanges()).map(p => p.copy())
fs.writeFileSync(path.join(workingDirPath, 'subdir-1', 'a.txt'), 'qux\nfoo\nbar\nbaz\n', 'utf8')
- await repo.refreshUnstagedChanges()
+ await repo.refresh()
+ await repo.getUnstagedChanges()
const [unstagedPatch2] = (await repo.getUnstagedChanges()).map(p => p.copy())
await repo.applyPatchToIndex(unstagedPatch1)
@@ -229,6 +274,8 @@ describe('Repository', function () {
)
unstagedLines.splice(11, 2, 'this is a modified line')
fs.writeFileSync(filePath, unstagedLines.join('\n'))
+ await repository.refresh()
+
const [unstagedFilePatch] = await repository.getUnstagedChanges()
const unstagedListener = sinon.spy()
unstagedFilePatch.onDidUpdate(unstagedListener)
@@ -423,7 +470,7 @@ describe('Repository', function () {
})
describe('merge conflicts', () => {
- describe('refreshMergeConflicts()', () => {
+ describe('getMergeConflicts()', () => {
it('returns a promise resolving to an array of MergeConflict objects', async () => {
const workingDirPath = await cloneRepository('merge-conflict')
const repo = await buildRepository(workingDirPath)
@@ -433,7 +480,8 @@ describe('Repository', function () {
// expected
}
- let mergeConflicts = await repo.refreshMergeConflicts()
+ await repo.refresh()
+ let mergeConflicts = await repo.getMergeConflicts()
const expected = [
{
path: 'added-to-both.txt',
@@ -470,7 +518,8 @@ describe('Repository', function () {
assertDeepPropertyVals(mergeConflicts, expected)
fs.unlinkSync(path.join(workingDirPath, 'removed-on-branch.txt'))
- mergeConflicts = await repo.refreshMergeConflicts()
+ await repo.refresh()
+ mergeConflicts = await repo.getMergeConflicts()
expected[3].fileStatus = 'deleted'
assertDeepPropertyVals(mergeConflicts, expected)
@@ -485,10 +534,11 @@ describe('Repository', function () {
// expected
}
- const mergeConflicts1 = await repo.refreshMergeConflicts()
+ await repo.refresh()
+ const mergeConflicts1 = await repo.getMergeConflicts()
await repo.stageFiles(['removed-on-master.txt'])
- const mergeConflicts2 = await repo.refreshMergeConflicts()
+ const mergeConflicts2 = await repo.getMergeConflicts()
assert.equal(mergeConflicts1.length, 5)
assert.equal(mergeConflicts2.length, 4)
@@ -518,39 +568,40 @@ describe('Repository', function () {
// expected
}
+ await repo.refresh()
const mergeConflictPaths = (await repo.getMergeConflicts()).map(c => c.getPath())
assert.deepEqual(mergeConflictPaths, ['added-to-both.txt', 'modified-on-both-ours.txt', 'modified-on-both-theirs.txt', 'removed-on-branch.txt', 'removed-on-master.txt'])
- let stagedFilePatches = await repo.refreshStagedChanges()
+ let stagedFilePatches = await repo.getStagedChanges()
assert.deepEqual(stagedFilePatches.map(patch => patch.getPath()), [])
await repo.stageFiles(['added-to-both.txt'])
- stagedFilePatches = await repo.refreshStagedChanges()
+ stagedFilePatches = await repo.getStagedChanges()
assert.deepEqual(stagedFilePatches.map(patch => patch.getPath()), ['added-to-both.txt'])
// choose version of the file on head
fs.writeFileSync(path.join(workingDirPath, 'modified-on-both-ours.txt'), 'master modification\n', 'utf8')
await repo.stageFiles(['modified-on-both-ours.txt'])
- stagedFilePatches = await repo.refreshStagedChanges()
+ stagedFilePatches = await repo.getStagedChanges()
// nothing additional to stage
assert.deepEqual(stagedFilePatches.map(patch => patch.getPath()), ['added-to-both.txt'])
// choose version of the file on branch
fs.writeFileSync(path.join(workingDirPath, 'modified-on-both-ours.txt'), 'branch modification\n', 'utf8')
await repo.stageFiles(['modified-on-both-ours.txt'])
- stagedFilePatches = await repo.refreshStagedChanges()
+ stagedFilePatches = await repo.getStagedChanges()
assert.deepEqual(stagedFilePatches.map(patch => patch.getPath()), ['added-to-both.txt', 'modified-on-both-ours.txt'])
// remove file that was deleted on branch
fs.unlinkSync(path.join(workingDirPath, 'removed-on-branch.txt'))
await repo.stageFiles(['removed-on-branch.txt'])
- stagedFilePatches = await repo.refreshStagedChanges()
+ stagedFilePatches = await repo.getStagedChanges()
assert.deepEqual(stagedFilePatches.map(patch => patch.getPath()), ['added-to-both.txt', 'modified-on-both-ours.txt', 'removed-on-branch.txt'])
// remove file that was deleted on master
fs.unlinkSync(path.join(workingDirPath, 'removed-on-master.txt'))
await repo.stageFiles(['removed-on-master.txt'])
- stagedFilePatches = await repo.refreshStagedChanges()
+ stagedFilePatches = await repo.getStagedChanges()
// nothing additional to stage
assert.deepEqual(stagedFilePatches.map(patch => patch.getPath()), ['added-to-both.txt', 'modified-on-both-ours.txt', 'removed-on-branch.txt'])
})
@@ -627,8 +678,8 @@ describe('Repository', function () {
await repo.abortMerge()
assert.equal(await repo.isMerging(), false)
- assert.equal((await repo.refreshStagedChanges()).length, 0)
- assert.equal((await repo.refreshUnstagedChanges()).length, 1)
+ assert.equal((await repo.getStagedChanges()).length, 0)
+ assert.equal((await repo.getUnstagedChanges()).length, 1)
assert.equal(fs.readFileSync(path.join(workingDirPath, 'fruit.txt')), 'a change\n')
})
})
@@ -644,8 +695,8 @@ describe('Repository', function () {
}
fs.writeFileSync(path.join(workingDirPath, 'animal.txt'), 'a change\n')
- const stagedChanges = await repo.refreshStagedChanges()
- const unstagedChanges = await repo.refreshUnstagedChanges()
+ const stagedChanges = await repo.getStagedChanges()
+ const unstagedChanges = await repo.getUnstagedChanges()
assert.equal(await repo.isMerging(), true)
try {
@@ -655,8 +706,8 @@ describe('Repository', function () {
assert.match(e.command, /^git merge --abort/)
}
assert.equal(await repo.isMerging(), true)
- assert.deepEqual(await repo.refreshStagedChanges(), stagedChanges)
- assert.deepEqual(await repo.refreshUnstagedChanges(), unstagedChanges)
+ assert.deepEqual(await repo.getStagedChanges(), stagedChanges)
+ assert.deepEqual(await repo.getUnstagedChanges(), unstagedChanges)
})
})
})
diff --git a/test/models/workspace-change-observer.test.js b/test/models/workspace-change-observer.test.js
index f3111ac395..92d4fc9450 100644
--- a/test/models/workspace-change-observer.test.js
+++ b/test/models/workspace-change-observer.test.js
@@ -70,7 +70,8 @@ describe('WorkspaceChangeObserver', () => {
assert.isTrue(changeSpy.calledOnce)
changeSpy.reset()
- const [unstagedChange] = await repository1.refreshUnstagedChanges()
+ repository1.refresh()
+ const [unstagedChange] = await repository1.getUnstagedChanges()
await repository1.applyPatchToIndex(unstagedChange)
await changeObserver.lastIndexChangePromise
assert.isTrue(changeSpy.called)
diff --git a/test/views/commit-view.test.js b/test/views/commit-view.test.js
index 2a7e579f5e..0808287e93 100644
--- a/test/views/commit-view.test.js
+++ b/test/views/commit-view.test.js
@@ -216,36 +216,40 @@ describe('CommitView', () => {
const view = new CommitView({workspace, commandRegistry, stagedChangesExist: false, lastCommit: {message: 'previous commit\'s message'}})
const {editor, amend} = view.refs
- // choose to keep current commit message when prompted
- confirmChoice = 1
editor.setText('some commit message')
-
await view.update({repository, stagedChangesExist: true})
+
+ // When checking amend with a commit message typed, prompt for whether
+ // to keep the current message or replace it with the last commit's message.
+ confirmChoice = 0
assert.isFalse(amend.checked)
+ assert.equal(editor.getText(), 'some commit message')
+
amend.click()
assert.isTrue(amend.checked)
+ assert.equal(atom.confirm.callCount, 1)
assert.equal(editor.getText(), 'some commit message')
- editor.setText('some commit message')
-
+ // When unchecking amend with a different commit message typed, keep the
+ // current message without prompting.
amend.click()
assert.isFalse(amend.checked)
+ assert.equal(atom.confirm.callCount, 1)
assert.equal(editor.getText(), 'some commit message')
- // choose to discard current commit message when prompted
- confirmChoice = 0
- editor.setText('some commit message')
-
- await view.update({repository, stagedChangesExist: true})
- assert.isFalse(amend.checked)
+ // When checking amend and choosing to discard the current message, replace
+ // the message with the last commit's message.
+ confirmChoice = 1
amend.click()
assert.isTrue(amend.checked)
+ assert.equal(atom.confirm.callCount, 2)
assert.equal(editor.getText(), 'previous commit\'s message')
- editor.setText('some commit message')
-
+ // When unchecking amend with the previous commit's message typed, clear
+ // the message box without prompting.
amend.click()
assert.isFalse(amend.checked)
+ assert.equal(atom.confirm.callCount, 2)
assert.equal(editor.getText(), '')
})
@@ -261,6 +265,19 @@ describe('CommitView', () => {
await view.commit()
assert.isFalse(amend.checked)
})
- })
+ it('calls props.setAmending() when the box is checked or unchecked', async function () {
+ const setAmending = sinon.spy()
+ const workdirPath = await cloneRepository('three-files')
+ const repository = await buildRepository(workdirPath)
+ const view = new CommitView({workspace, commandRegistry, stagedChangesExist: false, lastCommit: {message: 'previous commit\'s message'}, setAmending})
+ const {editor, amend} = view.refs
+
+ amend.click()
+ assert.deepEqual(setAmending.args, [[true]])
+
+ amend.click()
+ assert.deepEqual(setAmending.args, [[true], [false]])
+ })
+ })
})