Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Stashing] Stash Diff Viewer #7213

Merged
merged 50 commits into from Apr 11, 2019
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
7b17b90
add stub stash diff component
outofambit Apr 3, 2019
004b31e
moving along
outofambit Apr 4, 2019
d80a6ec
add field to stash model
outofambit Apr 5, 2019
be5d9ac
Update stash-test.ts
outofambit Apr 5, 2019
10a7fd1
add file list loading infra in stores
outofambit Apr 5, 2019
5c1cfae
some ui
outofambit Apr 5, 2019
864e5ea
fix container
outofambit Apr 8, 2019
5a99e3d
some styling
outofambit Apr 8, 2019
20d608a
add some state
outofambit Apr 8, 2019
4ec4327
use some state
outofambit Apr 8, 2019
8985b8e
lint
outofambit Apr 8, 2019
4c90278
even more state
outofambit Apr 8, 2019
2624fbf
use more state
outofambit Apr 8, 2019
70fb761
lint
outofambit Apr 8, 2019
fae2f2d
lint?
outofambit Apr 8, 2019
4eb8ce3
ugh prettier
outofambit Apr 8, 2019
0775ff1
use imageDiffType
outofambit Apr 8, 2019
6e86168
css stop gap measures
outofambit Apr 8, 2019
ac45172
make it Resizable
outofambit Apr 8, 2019
5350793
renderStashDiff -> renderStashDiffViewer
outofambit Apr 9, 2019
5abd3b3
rename file
outofambit Apr 9, 2019
df63cf0
Update stash-diff-viewer.tsx
outofambit Apr 9, 2019
b157c97
remove ternary from jsx
outofambit Apr 9, 2019
b4b2da4
newline
outofambit Apr 9, 2019
59b97b6
JSX syntax
outofambit Apr 9, 2019
3b1c625
trim function
outofambit Apr 9, 2019
9c33c94
merge stash and stash-entry model files
outofambit Apr 10, 2019
91f3827
fix import
outofambit Apr 10, 2019
fa866e0
stub header component
outofambit Apr 9, 2019
7a695a0
wurdz
outofambit Apr 9, 2019
db0e306
styling
outofambit Apr 9, 2019
3f6a10f
wiring up drop stash
outofambit Apr 10, 2019
fa5b722
wire up pop
outofambit Apr 10, 2019
a15af6f
add logging to clear
outofambit Apr 10, 2019
dde1572
whoops
outofambit Apr 10, 2019
8066e5a
Update dispatcher.ts
outofambit Apr 10, 2019
ad33b10
refresh after pop or drop
outofambit Apr 10, 2019
bb0c561
:pencil:
outofambit Apr 11, 2019
3c5f202
:pencil:
outofambit Apr 11, 2019
2a37935
use a class so we make functions less often
outofambit Apr 11, 2019
6b91bfc
fix hiding stash UI
outofambit Apr 11, 2019
7ca9301
more docs
outofambit Apr 11, 2019
318e131
clean up loadStashedFiles
outofambit Apr 11, 2019
a4b73f0
combine `_popStash` and `_popStashEntry`
outofambit Apr 11, 2019
2303fad
Apply suggestions from code review
shiftkey Apr 11, 2019
cb6e56d
liiiint
shiftkey Apr 11, 2019
2aaf6fe
type cleanup
outofambit Apr 11, 2019
593cdc3
superfluous emitUpdate
outofambit Apr 11, 2019
3c9e433
another unneeded emitUpdate
outofambit Apr 11, 2019
e1b1d6b
docs and unexport unused type
outofambit Apr 11, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions app/src/lib/app-state.ts
Expand Up @@ -152,6 +152,9 @@ export interface IAppState {
/** The width of the commit summary column in the history view */
readonly commitSummaryWidth: number

/** The width of the files list in the stash view */
readonly stashedFilesWidth: number

/** Whether we should hide the toolbar (and show inverted window controls) */
readonly titleBarStyle: 'light' | 'dark'

Expand Down Expand Up @@ -558,6 +561,12 @@ export interface IChangesState {

/** Whether or not to show the UI for a stash entry. */
readonly shouldShowStashedChanges: boolean

/** Currently selected file in the stash diff viewer UI (aka the file we want to show the diff for) */
readonly selectedStashedFile: CommittedFileChange | null

/** Currently selected file's diff */
readonly selectedStashedFileDiff: IDiff | null
}

/**
Expand Down
3 changes: 2 additions & 1 deletion app/src/lib/git/stash.ts
Expand Up @@ -2,7 +2,7 @@ import { git } from '.'
import { Repository } from '../../models/repository'
import { GitError, IGitResult } from './core'
import { GitError as DugiteError } from 'dugite'
import { IStashEntry } from '../../models/stash-entry'
import { IStashEntry, StashedChangesLoadStates } from '../../models/stash-entry'

export const DesktopStashEntryMarker = '!!GitHub_Desktop'

Expand Down Expand Up @@ -75,6 +75,7 @@ export async function getDesktopStashEntries(
name: `stash@{${ix}}`,
branchName: branchName,
stashSha: match[1],
files: { kind: StashedChangesLoadStates.NotLoaded },
})
}

Expand Down
102 changes: 91 additions & 11 deletions app/src/lib/stores/app-store.ts
Expand Up @@ -212,8 +212,10 @@ import {
createDesktopStashEntry,
getLastDesktopStashEntryForBranch,
popStashEntry,
dropDesktopStashEntry,
} from '../git/stash'
import { UncommittedChangesStrategy } from '../../models/uncommitted-changes-strategy'
import { IStashEntry } from '../../models/stash-entry'
import { RebaseFlowStep, RebaseStep } from '../../models/rebase-flow-step'
import { RebasePreview } from '../../models/rebase'

Expand All @@ -240,6 +242,9 @@ const sidebarWidthConfigKey: string = 'sidebar-width'
const defaultCommitSummaryWidth: number = 250
const commitSummaryWidthConfigKey: string = 'commit-summary-width'

const defaultStashedFilesWidth: number = 250
const stashedFilesWidthConfigKey: string = 'stashed-files-width'

const confirmRepoRemovalDefault: boolean = true
const confirmDiscardChangesDefault: boolean = true
const askForConfirmationOnForcePushDefault = true
Expand Down Expand Up @@ -316,6 +321,7 @@ export class AppStore extends TypedBaseStore<IAppState> {

private sidebarWidth: number = defaultSidebarWidth
private commitSummaryWidth: number = defaultCommitSummaryWidth
private stashedFilesWidth: number = defaultStashedFilesWidth
private windowState: WindowState
private windowZoomFactor: number = 1
private isUpdateAvailableBannerVisible: boolean = false
Expand Down Expand Up @@ -558,6 +564,7 @@ export class AppStore extends TypedBaseStore<IAppState> {
emoji: this.emoji,
sidebarWidth: this.sidebarWidth,
commitSummaryWidth: this.commitSummaryWidth,
stashedFilesWidth: this.stashedFilesWidth,
appMenuState: this.appMenu ? this.appMenu.openMenus : [],
titleBarStyle:
this.showWelcomeFlow || repositories.length === 0 ? 'light' : 'dark',
Expand Down Expand Up @@ -2575,7 +2582,16 @@ export class AppStore extends TypedBaseStore<IAppState> {
)

if (shouldPopStash) {
await this._popStash(repository, foundBranch)
const stash = await getLastDesktopStashEntryForBranch(
repository,
foundBranch.name
)

if (stash !== null) {
await this._popStashEntry(repository, stash)
} else {
log.warn('no stash found that matches')
}
}

try {
Expand Down Expand Up @@ -4736,19 +4752,37 @@ export class AppStore extends TypedBaseStore<IAppState> {
await createDesktopStashEntry(repository, branchName)
}

public async _popStash(repository: Repository, branch: Branch) {
const stash = await getLastDesktopStashEntryForBranch(
repository,
branch.name
/** This shouldn't be called directly. See `Dispatcher`. */
public async _popStashEntry(repository: Repository, stashEntry: IStashEntry) {
const gitStore = this.gitStoreCache.get(repository)
await gitStore.performFailableOperation(() => {
return popStashEntry(repository, stashEntry.stashSha)
shiftkey marked this conversation as resolved.
Show resolved Hide resolved
})
log.info(
`[AppStore. _popStashEntry] popped stash with commit id ${
stashEntry.stashSha
}`
)

if (stash === null) {
log.warn('no stash found that matches')
return
}
await this._refreshRepository(repository)
}

await popStashEntry(repository, stash.stashSha)
log.info(`Popped stash with commit id ${stash.stashSha}`)
/** This shouldn't be called directly. See `Dispatcher`. */
public async _dropStashEntry(
repository: Repository,
stashEntry: IStashEntry
) {
const gitStore = this.gitStoreCache.get(repository)
await gitStore.performFailableOperation(() => {
return dropDesktopStashEntry(repository, stashEntry.stashSha)
})
log.info(
`[AppStore. _dropStashEntry] dropped stash with commit id ${
stashEntry.stashSha
}`
)

await this._refreshRepository(repository)
}

/** This shouldn't be called directly. See `Dispatcher`. */
Expand Down Expand Up @@ -4777,6 +4811,52 @@ export class AppStore extends TypedBaseStore<IAppState> {

this.emitUpdate()
}

/** This shouldn't be called directly. See `Dispatcher`. */
public async _loadStashedFiles(
repository: Repository,
stashEntry: IStashEntry
) {
const gitStore = this.gitStoreCache.get(repository)
await gitStore.loadStashedFiles(stashEntry)
}

/** This shouldn't be called directly. See `Dispatcher`. */
public async _changeStashedFileSelection(
repository: Repository,
file: CommittedFileChange
): Promise<void> {
this.repositoryStateCache.updateChangesState(repository, () => ({
selectedStashedFile: file,
selectedStashedFileDiff: null,
}))
this.emitUpdate()

const diff = await getCommitDiff(repository, file, file.commitish)

this.repositoryStateCache.updateChangesState(repository, () => ({
selectedStashedFileDiff: diff,
}))

this.emitUpdate()
}

/** This shouldn't be called directly. See `Dispatcher`. */
public _setStashedFilesWidth(width: number): Promise<void> {
this.stashedFilesWidth = width
setNumber(stashedFilesWidthConfigKey, width)
this.emitUpdate()

return Promise.resolve()
}

public _resetStashedFilesWidth(): Promise<void> {
this.stashedFilesWidth = defaultStashedFilesWidth
localStorage.removeItem(stashedFilesWidthConfigKey)
this.emitUpdate()

return Promise.resolve()
}
}

/**
Expand Down
19 changes: 18 additions & 1 deletion app/src/lib/stores/git-store.ts
Expand Up @@ -63,6 +63,7 @@ import {
revSymmetricDifference,
getSymbolicRef,
getConfigValue,
getChangedFiles,
} from '../git'
import { RetryAction, RetryActionType } from '../../models/retry-actions'
import { UpstreamAlreadyExistsError } from './upstream-already-exists-error'
Expand All @@ -79,7 +80,7 @@ import { IGitAccount } from '../../models/git-account'
import { BaseStore } from './base-store'
import { enablePullWithRebase, enableStashing } from '../feature-flag'
import { getDesktopStashEntries } from '../git/stash'
import { IStashEntry } from '../../models/stash-entry'
import { IStashEntry, StashedChangesLoadStates } from '../../models/stash-entry'

/** The number of commits to load from history per batch. */
const CommitBatchSize = 100
Expand Down Expand Up @@ -999,6 +1000,22 @@ export class GitStore extends BaseStore {
return this._stashEntries
}

/**
* Updates the latest stash entry with a list of files that it changes
*/
public async loadStashedFiles(stashEntry: IStashEntry) {
const files = await getChangedFiles(this.repository, stashEntry.stashSha)

this._stashEntries.set(stashEntry.branchName, {
...stashEntry,
files: {
kind: StashedChangesLoadStates.Loaded,
files,
},
})
this.emitUpdate()
}

public async loadRemotes(): Promise<void> {
const remotes = await getRemotes(this.repository)
this._defaultRemote = findDefaultRemote(remotes)
Expand Down
2 changes: 2 additions & 0 deletions app/src/lib/stores/repository-state-cache.ts
Expand Up @@ -131,6 +131,8 @@ function getInitialRepositoryState(): IRepositoryState {
showCoAuthoredBy: false,
conflictState: null,
shouldShowStashedChanges: false,
selectedStashedFile: null,
selectedStashedFileDiff: null,
},
selectedSection: RepositorySectionTab.Changes,
branchesState: {
Expand Down
23 changes: 23 additions & 0 deletions app/src/models/stash-entry.ts
@@ -1,3 +1,5 @@
import { CommittedFileChange } from './status'

export interface IStashEntry {
/** The name of the entry i.e., `stash@{0}` */
readonly name: string
Expand All @@ -7,4 +9,25 @@ export interface IStashEntry {

/** The SHA of the commit object created as a result of stashing. */
readonly stashSha: string

/** The list of files this stash touches */
readonly files: StashedFileChanges
}

/** Whether file changes for a stash entry are loaded or not */
export enum StashedChangesLoadStates {
outofambit marked this conversation as resolved.
Show resolved Hide resolved
NotLoaded = 'NotLoaded',
Loading = 'Loading',
Loaded = 'Loaded',
}

type StashedFileChanges =
| {
kind:
| StashedChangesLoadStates.NotLoaded
| StashedChangesLoadStates.Loading
}
| {
kind: StashedChangesLoadStates.Loaded
files: ReadonlyArray<CommittedFileChange>
}
1 change: 1 addition & 0 deletions app/src/ui/app.tsx
Expand Up @@ -2184,6 +2184,7 @@ export class App extends React.Component<IAppProps, IAppState> {
emoji={state.emoji}
sidebarWidth={state.sidebarWidth}
commitSummaryWidth={state.commitSummaryWidth}
stashedFilesWidth={state.stashedFilesWidth}
issuesStore={this.props.issuesStore}
gitHubUserStore={this.props.gitHubUserStore}
onViewCommitOnGitHub={this.onViewCommitOnGitHub}
Expand Down
51 changes: 50 additions & 1 deletion app/src/ui/dispatcher/dispatcher.ts
Expand Up @@ -79,6 +79,7 @@ import {
import { MergeResult } from '../../models/merge'
import { UncommittedChangesStrategy } from '../../models/uncommitted-changes-strategy'
import { RebaseFlowStep, RebaseStep } from '../../models/rebase-flow-step'
import { IStashEntry } from '../../models/stash-entry'

/**
* An error handler function.
Expand Down Expand Up @@ -331,7 +332,10 @@ export class Dispatcher {
return
}

const updatedConflictState = { ...conflictState, targetBranch }
const updatedConflictState = {
...conflictState,
targetBranch,
}

this.repositoryStateManager.updateChangesState(repository, () => ({
conflictState: updatedConflictState,
Expand Down Expand Up @@ -1932,6 +1936,16 @@ export class Dispatcher {
return this.appStore._createStash(repository, branch.name)
}

/** Drops the given stash in the given repository */
public dropStash(repository: Repository, stashEntry: IStashEntry) {
return this.appStore._dropStashEntry(repository, stashEntry)
}

/** Pop the given stash in the given repository */
public popStash(repository: Repository, stashEntry: IStashEntry) {
return this.appStore._popStashEntry(repository, stashEntry)
}

/**
* Show the UI for stashed changes
*/
Expand All @@ -1945,4 +1959,39 @@ export class Dispatcher {
public hideStashEntry(repository: Repository) {
return this.appStore._hideStashEntry(repository)
}

/** Loads the list of changed files for the latest stash on this branch */
public loadStashedFiles(repository: Repository, stashEntry: IStashEntry) {
return this.appStore._loadStashedFiles(repository, stashEntry)
}

/**
* Change the selected changed file in the stash diff viewer.
*
* @param repository The currently active repository instance
*
* @param file
*/
public changeStashedFileSelection(
repository: Repository,
file: CommittedFileChange
): Promise<void> {
return this.appStore._changeStashedFileSelection(repository, file)
}

/**
* Set the width of the commit summary column in the
* history view to the given value.
*/
public setStashedFilesWidth = (width: number): Promise<void> => {
return this.appStore._setStashedFilesWidth(width)
}

/**
* Reset the width of the commit summary column in the
* history view to its default value.
*/
public resetStashedFilesWidth = (): Promise<void> => {
return this.appStore._resetStashedFilesWidth()
}
}