mirror of
https://github.com/desktop/desktop
synced 2024-10-30 17:25:09 +00:00
Add manual resolutions to continueCherryPick
This commit is contained in:
parent
29c23c029c
commit
f65b5aff52
2 changed files with 52 additions and 5 deletions
|
@ -17,6 +17,8 @@ import { ChildProcess } from 'child_process'
|
|||
import { round } from '../../ui/lib/round'
|
||||
import byline from 'byline'
|
||||
import { ICherryPickSnapshot } from '../../models/cherry-pick'
|
||||
import { ManualConflictResolution } from '../../models/manual-conflict-resolution'
|
||||
import { stageManualConflictResolution } from './stage'
|
||||
|
||||
/** The app-specific results from attempting to cherry pick commits*/
|
||||
export enum CherryPickResult {
|
||||
|
@ -203,7 +205,7 @@ function parseCherryPickResult(result: IGitResult): CherryPickResult {
|
|||
export async function getCherryPickSnapshot(
|
||||
repository: Repository
|
||||
): Promise<ICherryPickSnapshot | null> {
|
||||
if (isCherryPickHeadFound(repository)) {
|
||||
if (!isCherryPickHeadFound(repository)) {
|
||||
// If there no cherry pick head, there is no cherry pick in progress.
|
||||
return null
|
||||
}
|
||||
|
@ -302,13 +304,28 @@ export async function getCherryPickSnapshot(
|
|||
export async function continueCherryPick(
|
||||
repository: Repository,
|
||||
files: ReadonlyArray<WorkingDirectoryFileChange>,
|
||||
manualResolutions: ReadonlyMap<string, ManualConflictResolution> = new Map(),
|
||||
progressCallback?: (progress: ICherryPickProgress) => void
|
||||
): Promise<CherryPickResult> {
|
||||
// only stage files related to cherry pick
|
||||
const trackedFiles = files.filter(f => {
|
||||
return f.status.kind !== AppFileStatusKind.Untracked
|
||||
})
|
||||
await stageFiles(repository, trackedFiles)
|
||||
|
||||
// apply conflict resolutions
|
||||
for (const [path, resolution] of manualResolutions) {
|
||||
const file = files.find(f => f.path === path)
|
||||
if (file !== undefined) {
|
||||
await stageManualConflictResolution(repository, file, resolution)
|
||||
} else {
|
||||
log.error(
|
||||
`[continueCherryPick] couldn't find file ${path} even though there's a manual resolution for it`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const otherFiles = trackedFiles.filter(f => !manualResolutions.has(f.path))
|
||||
await stageFiles(repository, otherFiles)
|
||||
|
||||
const status = await getStatus(repository)
|
||||
if (status == null) {
|
||||
|
@ -320,7 +337,7 @@ export async function continueCherryPick(
|
|||
}
|
||||
|
||||
// make sure cherry pick is still in progress to continue
|
||||
if (await isCherryPickHeadFound(repository)) {
|
||||
if (await !isCherryPickHeadFound(repository)) {
|
||||
return CherryPickResult.Aborted
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,9 @@ import {
|
|||
continueCherryPick,
|
||||
getCherryPickSnapshot,
|
||||
} from '../../../src/lib/git/cherry-pick'
|
||||
import { isConflictedFile } from '../../../src/lib/status'
|
||||
import { Branch } from '../../../src/models/branch'
|
||||
import { ManualConflictResolution } from '../../../src/models/manual-conflict-resolution'
|
||||
import { ICherryPickProgress } from '../../../src/models/progress'
|
||||
import { Repository } from '../../../src/models/repository'
|
||||
import { AppFileStatusKind } from '../../../src/models/status'
|
||||
|
@ -279,7 +281,7 @@ describe('git/cherry-pick', () => {
|
|||
expect(conflictedFiles).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('successfully continues cherry picking with conflicts after resolving them', async () => {
|
||||
it('successfully continues cherry picking with conflicts after resolving them by overwriting', async () => {
|
||||
result = await cherryPick(repository, featureBranch.tip.sha)
|
||||
expect(result).toBe(CherryPickResult.ConflictsEncountered)
|
||||
|
||||
|
@ -312,6 +314,34 @@ describe('git/cherry-pick', () => {
|
|||
expect(result).toBe(CherryPickResult.CompletedWithoutError)
|
||||
})
|
||||
|
||||
it('successfully continues cherry picking with conflicts after resolving them manually', async () => {
|
||||
result = await cherryPick(repository, featureBranch.tip.sha)
|
||||
expect(result).toBe(CherryPickResult.ConflictsEncountered)
|
||||
|
||||
const statusAfterCherryPick = await getStatusOrThrow(repository)
|
||||
const { files } = statusAfterCherryPick.workingDirectory
|
||||
|
||||
// git diff --check warns if conflict markers exist and will exit with
|
||||
// non-zero status if conflicts found
|
||||
const diffCheckBefore = await GitProcess.exec(
|
||||
['diff', '--check'],
|
||||
repository.path
|
||||
)
|
||||
expect(diffCheckBefore.exitCode).toBeGreaterThan(0)
|
||||
|
||||
const manualResolutions = new Map<string, ManualConflictResolution>()
|
||||
|
||||
for (const file of files) {
|
||||
if (isConflictedFile(file.status)) {
|
||||
manualResolutions.set(file.path, ManualConflictResolution.theirs)
|
||||
}
|
||||
}
|
||||
|
||||
result = await continueCherryPick(repository, files, manualResolutions)
|
||||
|
||||
expect(result).toBe(CherryPickResult.CompletedWithoutError)
|
||||
})
|
||||
|
||||
it('successfully detects cherry picking with outstanding files not staged', async () => {
|
||||
result = await cherryPick(repository, featureBranch.tip.sha)
|
||||
expect(result).toBe(CherryPickResult.ConflictsEncountered)
|
||||
|
@ -462,7 +492,7 @@ describe('git/cherry-pick', () => {
|
|||
Path.join(repository.path, 'THING_THREE.md'),
|
||||
'# Resolve conflicts!'
|
||||
)
|
||||
result = await continueCherryPick(repository, files, p =>
|
||||
result = await continueCherryPick(repository, files, new Map(), p =>
|
||||
progress.push(p)
|
||||
)
|
||||
expect(result).toBe(CherryPickResult.CompletedWithoutError)
|
||||
|
|
Loading…
Reference in a new issue