@@ -266,8 +266,6 @@ import {
266266 listWorktrees ,
267267 unstageAll ,
268268 git ,
269- IGitStringExecutionOptions ,
270- IGitStringResult ,
271269} from '../git'
272270import {
273271 installGlobalLFSFilters ,
@@ -453,11 +451,6 @@ import {
453451 gatherCommitContext ,
454452} from '../copilot-conflict-context'
455453import { resolveWithin } from '../path'
456- import {
457- executionOptionsWithProgress ,
458- SingleBranchFetchProgressParser ,
459- } from '../progress'
460- import { envForRemoteOperation } from '../git/environment'
461454
462455const LastSelectedRepositoryIDKey = 'last-selected-repository-id'
463456
@@ -6082,171 +6075,6 @@ export class AppStore extends TypedBaseStore<IAppState> {
60826075 } )
60836076 }
60846077
6085- public async _fetchSingleBranch (
6086- repository : Repository ,
6087- branch : Branch
6088- ) : Promise < void > {
6089- const state = this . repositoryStateCache . get ( repository )
6090- // Don't allow concurrent network operations.
6091- if ( state . isPushPullFetchInProgress ) {
6092- this . _showPopup ( {
6093- type : PopupType . Error ,
6094- error : new Error (
6095- 'Another push/pull/fetch request is in progress.\nTry again after the ongoing request is finished'
6096- ) ,
6097- } )
6098- return
6099- }
6100-
6101- return this . withRefreshedGitHubRepository ( repository , repo => {
6102- return this . performFetchSingleBranch ( repo , branch )
6103- } )
6104- }
6105-
6106- /** This shouldn't be called directly. See `Dispatcher`. */
6107- private async performFetchSingleBranch (
6108- repository : Repository ,
6109- branch : Branch
6110- ) {
6111- const isRemote = branch . type === BranchType . Remote
6112-
6113- const remoteName = isRemote ? branch . remoteName : branch . upstreamRemoteName
6114- const remoteBranchName = isRemote
6115- ? branch . nameWithoutRemote
6116- : branch . upstreamWithoutRemote
6117-
6118- if ( ! remoteName ) {
6119- throw new Error ( 'Remote name not found' )
6120- }
6121- if ( ! remoteBranchName ) {
6122- throw new Error ( 'Remote branch not found' )
6123- }
6124-
6125- const isBackgroundTask = false
6126- const gitStore = this . gitStoreCache . get ( repository )
6127-
6128- // repository.url
6129- const remote = { name : remoteName , url : 'file://' }
6130-
6131- const progressCb = ( progress : IFetchProgress ) => {
6132- this . updatePushPullFetchProgress ( repository , progress )
6133- }
6134- const progressTitle = isRemote
6135- ? `Fetching ${ branch . name } `
6136- : `Fetching ${ remoteBranchName } `
6137- const kind = 'fetch'
6138-
6139- const fetchFn = async ( isRemote : boolean ) : Promise < IGitStringResult > => {
6140- let opts : IGitStringExecutionOptions = {
6141- successExitCodes : new Set ( [ 0 ] ) ,
6142- }
6143- if ( remote . url ) {
6144- opts = {
6145- ...opts ,
6146- env : await envForRemoteOperation ( remote . url ) ,
6147- }
6148- }
6149- opts = await executionOptionsWithProgress (
6150- { ...opts , trackLFSProgress : true , isBackgroundTask } ,
6151- new SingleBranchFetchProgressParser ( ) ,
6152- progress => {
6153- if ( progress . kind === 'context' ) {
6154- const text = progress . text
6155- if (
6156- ! text . startsWith ( 'remote: Counting objects' ) &&
6157- ! text . startsWith ( 'remote: Compressing objects' )
6158- ) {
6159- return
6160- }
6161- }
6162-
6163- const description =
6164- progress . kind === 'progress' ? progress . details . text : progress . text
6165- const value = progress . percent
6166-
6167- progressCb ( {
6168- kind,
6169- title : progressTitle ,
6170- description,
6171- value,
6172- remote : remote . name ,
6173- } )
6174- }
6175- )
6176- const flags = isRemote
6177- ? [ 'fetch' , '--progress' , '--recurse-submodules=on-demand' , remoteName ]
6178- : [
6179- 'fetch' ,
6180- '--progress' ,
6181- '--show-forced-updates' ,
6182- // '--no-write-fetch-head',
6183- '--recurse-submodules=on-demand' ,
6184- remoteName ,
6185- ]
6186-
6187- const branchTarget = isRemote
6188- ? remoteBranchName
6189- : `${ remoteBranchName } :${ remoteBranchName } `
6190- const actionName = isRemote ? 'fetchRemoteBranch' : 'fetchLocalBranch'
6191-
6192- const executionOpts = isRemote
6193- ? opts
6194- : {
6195- ...opts ,
6196- successExitCodes : new Set ( [ 0 , 1 ] ) ,
6197- }
6198-
6199- return await git (
6200- [ ...flags , branchTarget ] ,
6201- repository . path ,
6202- actionName ,
6203- executionOpts
6204- )
6205- }
6206-
6207- const execFetchFn = async ( ) => {
6208- // Initial progress
6209- progressCb ( {
6210- kind,
6211- title : progressTitle ,
6212- value : 0 ,
6213- remote : remote . name ,
6214- } )
6215-
6216- await gitStore . performFailableOperation (
6217- async ( ) => {
6218- const result = await fetchFn ( isRemote )
6219- if (
6220- ! isRemote &&
6221- result &&
6222- ( result . stderr ?. includes ( 'rejected' ) ||
6223- result . stderr ?. includes ( 'non-fast-forward' ) )
6224- ) {
6225- this . emitError (
6226- new ErrorWithMetadata ( new Error ( result . stderr ) , { repository } )
6227- )
6228- }
6229-
6230- await this . _refreshRepository ( repository )
6231- } ,
6232- {
6233- backgroundTask : isBackgroundTask ,
6234- }
6235- )
6236- }
6237-
6238- try {
6239- await this . withPushPullFetch ( repository , execFetchFn )
6240- } catch ( error ) {
6241- const errorWithMetadata = new ErrorWithMetadata ( error , {
6242- repository,
6243- } )
6244- this . emitError ( errorWithMetadata )
6245- } finally {
6246- this . updatePushPullFetchProgress ( repository , null )
6247- }
6248- }
6249-
62506078 public async _resetHardToUpstream ( repository : Repository ) : Promise < void > {
62516079 const { branchesState } = this . repositoryStateCache . get ( repository )
62526080 const { tip } = branchesState
@@ -6778,6 +6606,30 @@ export class AppStore extends TypedBaseStore<IAppState> {
67786606 } )
67796607 }
67806608
6609+ /**
6610+ * Attempts to fast-forward a branch to its upstream.
6611+ *
6612+ * @returns true if it was successful
6613+ */
6614+ public async _fastForwardBranch (
6615+ repository : Repository ,
6616+ branch : Branch
6617+ ) : Promise < void > {
6618+ if ( branch . upstream === null || branch . isGone ) {
6619+ throw new Error ( `The branch '${ branch . name } ' has not been published yet.` )
6620+ }
6621+ await this . _fetch ( repository , FetchType . UserInitiatedTask )
6622+ const stillDifferingBranches = await getBranchesDifferingFromUpstream (
6623+ repository
6624+ )
6625+ const stillDiffers = stillDifferingBranches . some ( b => b . ref === branch . ref )
6626+ if ( stillDiffers ) {
6627+ throw new Error (
6628+ `The branch '${ branch . name } ' cannot be fast-forwarded. Switch to it and pull it manually.`
6629+ )
6630+ }
6631+ }
6632+
67816633 /**
67826634 * Fetch a particular remote in a repository.
67836635 *
0 commit comments