Skip to content

Commit dea3ecf

Browse files
authored
Sessions - select the active branch in the branch picker (microsoft#296606)
* Git - observable repository state * Wire-up the active branch selection * Pull request feedback
1 parent 35c9204 commit dea3ecf

File tree

5 files changed

+32
-29
lines changed

5 files changed

+32
-29
lines changed

src/vs/sessions/contrib/chat/browser/branchPicker.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,9 @@ export class BranchPicker extends Disposable {
7878
.filter((name): name is string => !!name)
7979
.filter(name => !name.includes(COPILOT_WORKTREE_PATTERN));
8080

81-
// Select main, master, or the first branch by default
82-
const defaultBranch = this._branches.find(b => b === 'main')
81+
// Select active branch, main, master, or the first branch by default
82+
const defaultBranch = this._branches.find(b => b === repository.state.get().HEAD?.name)
83+
?? this._branches.find(b => b === 'main')
8384
?? this._branches.find(b => b === 'master')
8485
?? this._branches[0];
8586
if (defaultBranch) {

src/vs/workbench/api/browser/mainThreadGitExtensionService.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export class MainThreadGitExtensionService extends Disposable implements MainThr
9797

9898
// Create a new repository and store it in the maps
9999
const state = toGitRepositoryState(result.state);
100-
const repository = new GitRepository(this, repositoryRootUri, state);
100+
const repository = new GitRepository(repositoryRootUri, state, this);
101101

102102
this._repositories.set(result.handle, repository);
103103
this._repositoryHandles.set(repositoryRootUri, result.handle);
@@ -135,6 +135,7 @@ export class MainThreadGitExtensionService extends Disposable implements MainThr
135135
return;
136136
}
137137

138-
repository.setState(toGitRepositoryState(state));
138+
// Update the repository state
139+
repository.updateState(toGitRepositoryState(state));
139140
}
140141
}

src/vs/workbench/api/common/extHostGitExtensionService.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import type * as vscode from 'vscode';
77
import { Event } from '../../../base/common/event.js';
88
import { Disposable, DisposableStore } from '../../../base/common/lifecycle.js';
9+
import { observableFromEvent, waitForState } from '../../../base/common/observable.js';
910
import { URI, UriComponents } from '../../../base/common/uri.js';
1011
import { ExtensionIdentifier } from '../../../platform/extensions/common/extensions.js';
1112
import { createDecorator } from '../../../platform/instantiation/common/instantiation.js';
@@ -153,18 +154,20 @@ export class ExtHostGitExtensionService extends Disposable implements IExtHostGi
153154
};
154155
}
155156

156-
let repositoryState = repository.state;
157-
if (repository.state.HEAD === undefined) {
158-
// If the repository is not initialized, wait for it
159-
await Event.toPromise(repository.state.onDidChange, this._disposables);
160-
repositoryState = repository.state;
161-
}
157+
// Ensure that the repository state is initialized
158+
const repositoryStateObs = observableFromEvent(this,
159+
repository.state.onDidChange, () => repository.state);
160+
await waitForState(repositoryStateObs, state => !!state.HEAD);
161+
162+
const repositoryState = repositoryStateObs.get();
162163

164+
// Store the repository and its handle in the maps
163165
const handle = ExtHostGitExtensionService._handlePool++;
164166

165167
this._repositories.set(handle, repository);
166168
this._repositoryByUri.set(repository.rootUri, handle);
167169

170+
// Subscribe to repository state changes
168171
this._disposables.add(repository.state.onDidChange(() => {
169172
this._proxy.$onDidChangeRepository(handle);
170173
}));
@@ -173,7 +176,9 @@ export class ExtHostGitExtensionService extends Disposable implements IExtHostGi
173176
handle,
174177
rootUri: repository.rootUri,
175178
state: {
176-
HEAD: repositoryState.HEAD ? toGitBranchDto(repositoryState.HEAD) : undefined
179+
HEAD: repositoryState.HEAD
180+
? toGitBranchDto(repositoryState.HEAD)
181+
: undefined
177182
}
178183
};
179184
}

src/vs/workbench/contrib/git/browser/gitService.ts

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { CancellationToken } from '../../../../base/common/cancellation.js';
7-
import { Emitter, Event } from '../../../../base/common/event.js';
87
import { BugIndicatingError } from '../../../../base/common/errors.js';
98
import { Disposable, IDisposable, toDisposable } from '../../../../base/common/lifecycle.js';
109
import { URI } from '../../../../base/common/uri.js';
1110
import { IGitService, IGitExtensionDelegate, GitRef, GitRefQuery, IGitRepository, GitRepositoryState } from '../common/gitService.js';
11+
import { ISettableObservable, observableValueOpts } from '../../../../base/common/observable.js';
12+
import { structuralEquals } from '../../../../base/common/equals.js';
1213

1314
export class GitService extends Disposable implements IGitService {
1415
declare readonly _serviceBrand: undefined;
@@ -44,25 +45,22 @@ export class GitService extends Disposable implements IGitService {
4445
}
4546

4647
export class GitRepository extends Disposable implements IGitRepository {
47-
private readonly _onDidChangeState = this._register(new Emitter<void>());
48-
readonly onDidChangeState: Event<void> = this._onDidChangeState.event;
48+
readonly rootUri: URI;
4949

50-
private _state: GitRepositoryState;
51-
get state(): GitRepositoryState { return this._state; }
52-
53-
setState(state: GitRepositoryState): void {
54-
this._state = state;
55-
this._onDidChangeState.fire();
50+
readonly state: ISettableObservable<GitRepositoryState>;
51+
updateState(state: GitRepositoryState): void {
52+
this.state.set(state, undefined);
5653
}
5754

5855
constructor(
59-
private readonly delegate: IGitExtensionDelegate,
60-
readonly rootUri: URI,
61-
state: GitRepositoryState
56+
rootUri: URI,
57+
initialState: GitRepositoryState,
58+
private readonly delegate: IGitExtensionDelegate
6259
) {
6360
super();
6461

65-
this._state = state;
62+
this.rootUri = rootUri;
63+
this.state = observableValueOpts({ owner: this, equalsFn: structuralEquals }, initialState);
6664
}
6765

6866
async getRefs(query: GitRefQuery, token?: CancellationToken): Promise<GitRef[]> {

src/vs/workbench/contrib/git/common/gitService.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { CancellationToken } from '../../../../base/common/cancellation.js';
7-
import { Event } from '../../../../base/common/event.js';
87
import { IDisposable } from '../../../../base/common/lifecycle.js';
8+
import { IObservable } from '../../../../base/common/observable.js';
99
import { URI } from '../../../../base/common/uri.js';
1010
import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
1111

@@ -48,10 +48,8 @@ export interface GitUpstreamRef {
4848
export interface IGitRepository {
4949
readonly rootUri: URI;
5050

51-
readonly state: GitRepositoryState;
52-
setState(state: GitRepositoryState): void;
53-
54-
readonly onDidChangeState: Event<void>;
51+
readonly state: IObservable<GitRepositoryState>;
52+
updateState(state: GitRepositoryState): void;
5553

5654
getRefs(query: GitRefQuery, token?: CancellationToken): Promise<GitRef[]>;
5755
}

0 commit comments

Comments
 (0)