(WIP) some work

This commit is contained in:
Sergio Padrino 2023-09-01 09:51:10 +02:00
parent 2e2c010d02
commit 61a952930f
3 changed files with 39 additions and 27 deletions

View file

@ -37,6 +37,11 @@ export enum RebaseResult {
* signal success to the user. * signal success to the user.
*/ */
CompletedWithoutError = 'CompletedWithoutError', CompletedWithoutError = 'CompletedWithoutError',
/**
* Git completed the rebase without reporting any errors, but the branch was
* already up to date and there was nothing to do.
*/
BranchAlreadyUpToDate = 'BranchAlreadyUpToDate',
/** /**
* The rebase encountered conflicts while attempting to rebase, and these * The rebase encountered conflicts while attempting to rebase, and these
* need to be resolved by the user before the rebase can continue. * need to be resolved by the user before the rebase can continue.
@ -61,6 +66,17 @@ export enum RebaseResult {
Error = 'Error', Error = 'Error',
} }
export function isSuccessfulRebaseResult(
result: RebaseResult
): result is
| RebaseResult.CompletedWithoutError
| RebaseResult.BranchAlreadyUpToDate {
return [
RebaseResult.CompletedWithoutError,
RebaseResult.BranchAlreadyUpToDate,
].includes(result)
}
/** /**
* Check the `.git/REBASE_HEAD` file exists in a repository to confirm * Check the `.git/REBASE_HEAD` file exists in a repository to confirm
* a rebase operation is underway. * a rebase operation is underway.
@ -402,6 +418,10 @@ export async function abortRebase(repository: Repository) {
function parseRebaseResult(result: IGitResult): RebaseResult { function parseRebaseResult(result: IGitResult): RebaseResult {
if (result.exitCode === 0) { if (result.exitCode === 0) {
if (result.stdout.trim().match(/^Current branch [^ ]+ is up to date.$/i)) {
return RebaseResult.BranchAlreadyUpToDate
}
return RebaseResult.CompletedWithoutError return RebaseResult.CompletedWithoutError
} }

View file

@ -33,6 +33,7 @@ import {
getBranches, getBranches,
getRebaseSnapshot, getRebaseSnapshot,
getRepositoryType, getRepositoryType,
isSuccessfulRebaseResult,
} from '../../lib/git' } from '../../lib/git'
import { isGitOnPath } from '../../lib/is-git-on-path' import { isGitOnPath } from '../../lib/is-git-on-path'
import { import {
@ -1211,7 +1212,7 @@ export class Dispatcher {
baseBranch.name, baseBranch.name,
targetBranch.name targetBranch.name
) )
} else if (result === RebaseResult.CompletedWithoutError) { } else if (isSuccessfulRebaseResult(result)) {
if (tip.kind !== TipState.Valid) { if (tip.kind !== TipState.Valid) {
log.warn( log.warn(
`[rebase] tip after completing rebase is ${tip.kind} but this should be a valid tip if the rebase completed without error` `[rebase] tip after completing rebase is ${tip.kind} but this should be a valid tip if the rebase completed without error`
@ -1259,7 +1260,7 @@ export class Dispatcher {
manualResolutions manualResolutions
) )
if (result === RebaseResult.CompletedWithoutError) { if (result === RebaseResult.ConflictsEncountered) {
this.statsStore.recordOperationSuccessfulWithConflicts(kind) this.statsStore.recordOperationSuccessfulWithConflicts(kind)
} }
@ -3627,7 +3628,8 @@ export class Dispatcher {
// conflict flow if squash results in conflict. // conflict flow if squash results in conflict.
const status = await this.appStore._loadStatus(repository) const status = await this.appStore._loadStatus(repository)
switch (result) { switch (result) {
case RebaseResult.CompletedWithoutError: case (RebaseResult.CompletedWithoutError,
RebaseResult.BranchAlreadyUpToDate):
if (status !== null && status.currentTip !== undefined) { if (status !== null && status.currentTip !== undefined) {
// This sets the history to the current tip // This sets the history to the current tip
// TODO: Look at history back to last retained commit and search for // TODO: Look at history back to last retained commit and search for
@ -3642,7 +3644,9 @@ export class Dispatcher {
await this.completeMultiCommitOperation( await this.completeMultiCommitOperation(
repository, repository,
totalNumberOfCommits result === RebaseResult.BranchAlreadyUpToDate
? 0
: totalNumberOfCommits
) )
break break
case RebaseResult.ConflictsEncountered: case RebaseResult.ConflictsEncountered:

View file

@ -1,4 +1,4 @@
import { getCommitsBetweenCommits, getMergeBase } from '../../lib/git' import { getCommitsBetweenCommits } from '../../lib/git'
import { promiseWithMinimumTimeout } from '../../lib/promise' import { promiseWithMinimumTimeout } from '../../lib/promise'
import { Branch } from '../../models/branch' import { Branch } from '../../models/branch'
import { ComputedAction } from '../../models/computed-action' import { ComputedAction } from '../../models/computed-action'
@ -42,21 +42,15 @@ export async function updateRebasePreview(
kind: ComputedAction.Loading, kind: ComputedAction.Loading,
}) })
const { commits, base } = await promiseWithMinimumTimeout(async () => { const commits = await promiseWithMinimumTimeout(
const commits = await getCommitsBetweenCommits( () =>
repository, getCommitsBetweenCommits(
baseBranch.tip.sha, repository,
targetBranch.tip.sha baseBranch.tip.sha,
) targetBranch.tip.sha
),
const base = await getMergeBase( 500
repository, )
baseBranch.tip.sha,
targetBranch.tip.sha
)
return { commits, base }
}, 500)
// if the branch being track has changed since we started this work, abandon // if the branch being track has changed since we started this work, abandon
// any further state updates (this function is re-entrant if the user is // any further state updates (this function is re-entrant if the user is
@ -75,14 +69,8 @@ export async function updateRebasePreview(
return return
} }
// the target branch is a direct descendant of the base branch
// which means the target branch is already up to date and the commits
// do not need to be applied
const isDirectDescendant = base === baseBranch.tip.sha
const commitsOrIgnore = isDirectDescendant ? [] : commits
onUpdate({ onUpdate({
kind: ComputedAction.Clean, kind: ComputedAction.Clean,
commits: commitsOrIgnore, commits,
}) })
} }