Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
20393f7
Add GSOS#getStatus and write test for staged/unstaged files
kuychaco Nov 9, 2016
eaed1c6
Add GSOS.getStatus test for merge conflict situation
kuychaco Nov 9, 2016
216ffae
:fire: unnecessary method GSOS.getMergeConflictFileStatus
kuychaco Nov 9, 2016
bce05b4
Rename GSOS.getStatus -> GSOS.getStatusesForChangedFiles
kuychaco Nov 9, 2016
43f80cd
:fire: old unused files
kuychaco Nov 10, 2016
0b5e0c3
Modify GSOS.getStatusesForChangedFiles() to handle renamed files
kuychaco Nov 15, 2016
2ef4f3e
Implement and use Repository#getStatusesForChangedFiles
kuychaco Nov 15, 2016
4779ac6
Fix more tests
kuychaco Nov 16, 2016
aa6c99f
Set initial CompositeListSelection active index to be first non-empty…
kuychaco Nov 16, 2016
d24d863
In StagingView do not update component on double-click of file path
kuychaco Nov 16, 2016
067e63f
:art: fetchChangedFilesCount and include merge conflict files
kuychaco Nov 16, 2016
a96a4aa
Only report selected item if there is an item to select
kuychaco Nov 16, 2016
335e976
Display changed files icon and count even when no files are changed
kuychaco Nov 16, 2016
3b782d6
:fire: console.log
kuychaco Nov 16, 2016
7d8b209
:fire: unnecessary test file
kuychaco Nov 16, 2016
5bfd251
Display FilePatch when file name is selected and fix tests
kuychaco Nov 16, 2016
347bb56
Update FilePatchView when repository is updated
kuychaco Nov 16, 2016
43e3549
Correctly display changes relative to HEAD~ when amending
kuychaco Nov 17, 2016
0908170
:fire: code for updating FilePatch objects
kuychaco Nov 17, 2016
5a65a4d
Fix more tests
kuychaco Nov 17, 2016
eb44ea5
:art: RepositoryObserver -> ModelObserver
kuychaco Nov 17, 2016
9d889fe
Fix test
kuychaco Nov 17, 2016
1fab5dd
Use injected workspace rather than atom.workspace
kuychaco Nov 18, 2016
e3177e6
Only have DOM-related logic in writeAfterUpdate hook
kuychaco Nov 18, 2016
710bfba
Rely on file system change events to trigger repository refresh
kuychaco Nov 18, 2016
e2d3242
Destroy FilePatch and StatusBarTile controllers in GithubPackage#destroy
kuychaco Nov 18, 2016
b048821
Flag tests that have red in console for further investigation
kuychaco Nov 18, 2016
1b4bf5a
:fire: MergeConflict objects
kuychaco Nov 18, 2016
bfc6fb5
Simplify FilePatch objects and remove emitter
kuychaco Nov 18, 2016
f4bd6f2
Cache FilePatch objects and clear them when the repository is refreshed
kuychaco Nov 18, 2016
01caf54
:art: combine optional parameters for `getFilePatchForPath` into opti…
kuychaco Nov 18, 2016
52b8106
Fix :bug: getting diff for untracked file. Add tests.
kuychaco Nov 18, 2016
a729cbc
Un-ignore tests
kuychaco Nov 18, 2016
6449d94
:art: GithubPackage#didSelectFilePatch
kuychaco Nov 18, 2016
4cee023
Improve test for cached FilePatch objects
kuychaco Nov 18, 2016
4dd1bf8
Await active model update before re-rendering
kuychaco Nov 19, 2016
edf4d70
Merge remote-tracking branch 'origin/master' into ku-diff-on-demand
kuychaco Nov 19, 2016
f6a787c
Fix test
kuychaco Nov 20, 2016
b5299a0
Only activate FilePatchView if `activate` option is passed to `didSel…
kuychaco Nov 20, 2016
b96204c
Focus FilePatchView on left arrow / "git:focus-diff-view" command
kuychaco Nov 21, 2016
99af683
Correct test description
kuychaco Nov 21, 2016
291ac08
:art: rearrange methods in Repository
kuychaco Nov 21, 2016
fa70e74
Fix :bug: in GSOS#diffFileStatus - only list new files if no staged opt
kuychaco Nov 21, 2016
bb9326c
Preserve amend status when update happens after repo refresh
kuychaco Nov 21, 2016
61ffd8b
Rename didSelectFilePatch -> didSelectFilePath
kuychaco Nov 22, 2016
e1b024a
:art: rename top-level methods for clarity
kuychaco Nov 22, 2016
b6a9a49
:art: reportSelectedItem -> onDidChangeSelectedItem
kuychaco Nov 22, 2016
432000a
Extract logic into method selectFirstNonEmptyList for clarity
kuychaco Nov 22, 2016
3258d79
:art: GSOS#diff -> GSOS#getDiffForFilePath
kuychaco Nov 22, 2016
f020a00
Add test for updating FilePatchController when repository is updated
kuychaco Nov 22, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 0 additions & 69 deletions lib/controllers/changed-files-count-controller.js

This file was deleted.

22 changes: 9 additions & 13 deletions lib/controllers/file-patch-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {Emitter, CompositeDisposable} from 'atom'
import etch from 'etch'

import FilePatchView from '../views/file-patch-view'
import ModelObserver from '../models/model-observer'

export default class FilePatchController {
constructor (props) {
Expand All @@ -14,28 +15,23 @@ export default class FilePatchController {
this.unstageHunk = this.unstageHunk.bind(this)
this.stageLines = this.stageLines.bind(this)
this.unstageLines = this.unstageLines.bind(this)
this.observeFilePatch()
this.repositoryObserver = new ModelObserver({
didUpdate: () => this.props.onRepoRefresh && this.props.onRepoRefresh()
})
this.repositoryObserver.setActiveModel(props.repository)
etch.initialize(this)
}

update (props) {
this.props = props
this.observeFilePatch()
async update (props) {
this.props = Object.assign({}, this.props, props)
this.emitter.emit('did-change-title', this.getTitle())
await this.repositoryObserver.setActiveModel(props.repository)
return etch.update(this)
}

observeFilePatch () {
if (this.filePatchSubscriptions) this.filePatchSubscriptions.dispose()
this.filePatchSubscriptions = new CompositeDisposable(
this.props.filePatch.onDidUpdate(this.didUpdateFilePatch.bind(this)),
this.props.filePatch.onDidDestroy(this.didDestroyFilePatch.bind(this))
)
}

destroy () {
this.emitter.emit('did-destroy')
this.filePatchSubscriptions.dispose()
this.repositoryObserver.destroy()
return etch.destroy(this)
}

Expand Down
12 changes: 9 additions & 3 deletions lib/controllers/git-panel-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ export default class GitPanelController {
workspace={this.props.workspace}
commandRegistry={this.props.commandRegistry}
notificationManager={this.props.notificationManager}
didSelectFilePatch={this.props.didSelectFilePatch}
didSelectFilePath={this.props.didSelectFilePath}
didSelectMergeConflictFile={this.props.didSelectMergeConflictFile}
focusFilePatchView={this.props.focusFilePatchView}
stageFilePatch={this.stageFilePatch}
unstageFilePatch={this.unstageFilePatch}
stageFiles={this.stageFiles}
Expand All @@ -64,9 +65,14 @@ export default class GitPanelController {
)
}

update (props) {
async update (props) {
this.props = Object.assign({}, this.props, props)
return this.repositoryObserver.setActiveModel(props.repository)
await this.repositoryObserver.setActiveModel(props.repository)
return etch.update(this)
}

destroy () {
this.repositoryObserver.destroy()
}

getLastModelDataRefreshPromise () {
Expand Down
18 changes: 12 additions & 6 deletions lib/controllers/status-bar-tile-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ export default class StatusBarTileController {
etch.initialize(this)
}

update (props) {
async update (props) {
this.props = Object.assign({}, this.props, props)
this.repositoryObserver.setActiveModel(props.repository)
await this.repositoryObserver.setActiveModel(props.repository)
return etch.update(this)
}

Expand Down Expand Up @@ -142,11 +142,16 @@ export default class StatusBarTileController {

async fetchChangedFilesCount (repository) {
const changedFiles = new Set()
for (let filePatch of await repository.getUnstagedChanges()) {
changedFiles.add(filePatch.getPath())
const {stagedFiles, unstagedFiles, mergeConflictFiles} = await repository.getStatusesForChangedFiles()

for (let filePath in unstagedFiles) {
changedFiles.add(filePath)
}
for (let filePath in stagedFiles) {
changedFiles.add(filePath)
}
for (let filePatch of await repository.getStagedChanges()) {
changedFiles.add(filePatch.getPath())
for (let filePath in mergeConflictFiles) {
changedFiles.add(filePath)
}
return changedFiles.size
}
Expand Down Expand Up @@ -189,5 +194,6 @@ export default class StatusBarTileController {
destroy () {
this.branchTooltipDisposable && this.branchTooltipDisposable.dispose()
this.pushPullTooltipDisposable && this.pushPullTooltipDisposable.dispose()
this.repositoryObserver.destroy()
}
}
105 changes: 64 additions & 41 deletions lib/git-shell-out-strategy.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,59 @@ export default class GitShellOutStrategy {
/**
* File Status and Diffs
*/
async getStatusesForChangedFiles () {
const output = await this.exec(['status', '--untracked-files=all', '-z'])

const statusMap = {
A: 'added',
M: 'modified',
D: 'deleted',
U: 'modified',
'?': 'added'
}

const stagedFiles = {}
const unstagedFiles = {}
const mergeConflictFiles = {}
const statusToHead = await this.diffFileStatus({target: 'HEAD'})

if (output) {
const lines = output.split('\0')
for (let i = 0; i < lines.length; i++) {
const line = lines[i]
if (line === '') continue
const [_, x, y, filePath] = line.match(/(.)(.)\s(.*)/)
if (x === 'U' || y === 'U' || (x === 'A' && y === 'A')) {
mergeConflictFiles[filePath] = {
ours: statusMap[x],
theirs: statusMap[y],
file: statusToHead[filePath] || 'equivalent'
}
continue
}
if (x === 'R') {
stagedFiles[filePath] = 'added'
stagedFiles[lines[++i]] = 'deleted'
continue
}
if (y !== ' ') {
unstagedFiles[filePath] = statusMap[y]
}
if (x !== ' ' && x !== '?') {
stagedFiles[filePath] = statusMap[x]
}
}
}

return {stagedFiles, unstagedFiles, mergeConflictFiles}
}

async diffFileStatus (options = {}) {
const args = ['diff', '--name-status', '--no-renames']
if (options.staged) args.push('--staged')
if (options.target) args.push(options.target)
if (options.diffFilter === 'unmerged') args.push('--diff-filter=U')
const output = await this.exec(args)
const untracked = await this.getUntrackedFiles()

const statusMap = {
A: 'added',
Expand All @@ -145,11 +191,14 @@ export default class GitShellOutStrategy {
}

const fileStatuses = {}
untracked.forEach(filePath => { fileStatuses[filePath] = 'added' })
output && output.trim().split(LINE_ENDING_REGEX).forEach(line => {
const [status, filePath] = line.split(' ')
fileStatuses[filePath] = statusMap[status]
})
if (!options.staged) {
const untracked = await this.getUntrackedFiles()
untracked.forEach(filePath => { fileStatuses[filePath] = 'added' })
}
return fileStatuses
}

Expand All @@ -159,27 +208,25 @@ export default class GitShellOutStrategy {
return output.trim().split(LINE_ENDING_REGEX)
}

async diff (options = {}) {
const args = ['diff', '--no-prefix', '--no-renames', '--diff-filter=u']
if (options.staged) args.push('--staged')
if (options.baseCommit) args.push(options.baseCommit)
async getDiffForFilePath (filePath, {staged, baseCommit} = {}) {
let args = ['diff', '--no-prefix', '--no-renames', '--diff-filter=u']
if (staged) args.push('--staged')
if (baseCommit) args.push(baseCommit)
args = args.concat(['--', filePath])
let output = await this.exec(args)

let rawDiffs = []
if (output) rawDiffs = parseDiff(output).filter(rawDiff => rawDiff.status !== 'unmerged')

if (!options.staged) {
// add untracked files
const untrackedFilePatches = await Promise.all((await this.getUntrackedFiles()).map(async (filePath) => {
const absPath = path.join(this.workingDir, filePath)
const stats = await fsStat(absPath)
const contents = await readFile(absPath)
return buildAddedFilePatch(filePath, contents, stats)
}))
rawDiffs = rawDiffs.concat(untrackedFilePatches)
if (!staged && (await this.getUntrackedFiles()).includes(filePath)) {
// add untracked file
const absPath = path.join(this.workingDir, filePath)
const stats = await fsStat(absPath)
const contents = await readFile(absPath)
rawDiffs.push(buildAddedFilePatch(filePath, contents, stats))
}

return rawDiffs.sort((a, b) => (a.newPath || a.oldPath).localeCompare(b.newPath || b.oldPath))
if (rawDiffs.length > 1) throw new Error(`Expected 0 or 1 diffs for ${filePath} but got ${rawDiffs.length}`)
return rawDiffs[0]
}

/**
Expand All @@ -205,30 +252,6 @@ export default class GitShellOutStrategy {
return this.exec(['merge', branchName])
}

async getMergeConflictFileStatus () {
const output = await this.exec(['status', '--short'])
const statusToHead = await this.diffFileStatus({target: 'HEAD'})

const statusMap = {
A: 'added',
U: 'modified',
D: 'deleted'
}

const statusesByPath = {}
output && output.trim().split(LINE_ENDING_REGEX).forEach(line => {
const [oursTheirsStatus, filePath] = line.split(' ')
if (['DD', 'AU', 'UD', 'UA', 'DU', 'AA', 'UU'].includes(oursTheirsStatus)) {
statusesByPath[filePath] = {
ours: statusMap[oursTheirsStatus[0]],
theirs: statusMap[oursTheirsStatus[1]],
file: statusToHead[filePath] || 'equivalent'
}
}
})
return statusesByPath
}

async isMerging () {
try {
await readFile(path.join(this.workingDir, '.git', 'MERGE_HEAD'))
Expand Down
Loading