Skip to content

Commit d1a1a93

Browse files
committed
Refactor repository selection with interactive picker and improve unstaging logic
1 parent 7c99811 commit d1a1a93

2 files changed

Lines changed: 82 additions & 25 deletions

File tree

packages/vscode/src/utils/git-repository-utils.ts

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as vscode from 'vscode'
22
import { execSync } from 'child_process'
33
import { dictionary } from '@shared/constants/dictionary'
4+
import * as path from 'path'
45

56
export interface GitRepository {
67
rootUri: vscode.Uri
@@ -16,9 +17,9 @@ export interface GitRepository {
1617
show: (ref: string, path: string) => Promise<string>
1718
}
1819

19-
export function get_git_repository(
20+
export async function get_git_repository(
2021
source_control?: vscode.SourceControl
21-
): GitRepository | null {
22+
): Promise<GitRepository | null> {
2223
const git_extension = vscode.extensions.getExtension('vscode.git')
2324
if (!git_extension) {
2425
vscode.window.showErrorMessage(
@@ -28,7 +29,7 @@ export function get_git_repository(
2829
}
2930

3031
const git_api = git_extension.exports.getAPI(1)
31-
const repositories = git_api.repositories
32+
const repositories: GitRepository[] = git_api.repositories
3233

3334
if (!repositories || repositories.length === 0) {
3435
vscode.window.showErrorMessage(
@@ -37,28 +38,52 @@ export function get_git_repository(
3738
return null
3839
}
3940

40-
let repository
41-
42-
// If source_control is provided and has rootUri, find matching repository
4341
if (source_control?.rootUri) {
44-
repository = repositories.find(
45-
(repo: any) =>
46-
repo.rootUri.toString() === source_control.rootUri!.toString()
42+
const repository = repositories.find(
43+
(repo) => repo.rootUri.toString() === source_control.rootUri!.toString()
4744
)
45+
if (repository) {
46+
return repository
47+
}
48+
}
49+
50+
if (repositories.length === 1) {
51+
return repositories[0]
4852
}
4953

50-
// If no repository found or source_control not provided, use first repository
51-
if (!repository) {
52-
repository = repositories[0]
53-
if (!repository) {
54-
vscode.window.showErrorMessage(
55-
dictionary.error_message.REPOSITORY_NOT_FOUND
56-
)
57-
return null
54+
const repositories_with_changes = repositories.filter(
55+
(repo) =>
56+
repo.state.indexChanges.length > 0 ||
57+
repo.state.workingTreeChanges.length > 0
58+
)
59+
60+
const repositories_to_show =
61+
repositories_with_changes.length > 0
62+
? repositories_with_changes
63+
: repositories
64+
65+
if (repositories_to_show.length === 1) {
66+
return repositories_to_show[0]
67+
}
68+
69+
const picks = repositories_to_show.map((repo) => {
70+
const folder = vscode.workspace.getWorkspaceFolder(repo.rootUri)
71+
return {
72+
label: folder ? folder.name : path.basename(repo.rootUri.fsPath),
73+
description: repo.rootUri.fsPath,
74+
repository: repo
5875
}
76+
})
77+
78+
const selected = await vscode.window.showQuickPick(picks, {
79+
placeHolder: 'Select a repository to generate the commit message for'
80+
})
81+
82+
if (!selected) {
83+
return null
5984
}
6085

61-
return repository
86+
return selected.repository
6287
}
6388

6489
export async function prepare_staged_changes(

packages/vscode/src/views/panel/backend/message-handlers/handle-commit-changes/handle-commit-changes.ts

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,33 @@ import * as path from 'path'
1111
import { execSync } from 'child_process'
1212
import { handle_accept_commit_message } from '../handle-accept-commit-message'
1313

14+
function unstage_changes(repository: GitRepository) {
15+
let has_commits = false
16+
try {
17+
execSync('git rev-parse HEAD', {
18+
cwd: repository.rootUri.fsPath,
19+
stdio: 'ignore'
20+
})
21+
has_commits = true
22+
} catch (e) {
23+
has_commits = false
24+
}
25+
26+
try {
27+
if (has_commits) {
28+
execSync('git reset', { cwd: repository.rootUri.fsPath })
29+
} else {
30+
execSync('git rm --cached -r .', { cwd: repository.rootUri.fsPath })
31+
}
32+
} catch (error) {
33+
Logger.error({
34+
function_name: 'unstage_changes',
35+
message: 'Failed to unstage changes',
36+
data: error
37+
})
38+
}
39+
}
40+
1441
async function proceed_with_commit_generation(
1542
panel_provider: PanelProvider,
1643
repository: GitRepository,
@@ -20,7 +47,7 @@ async function proceed_with_commit_generation(
2047
const api_config = await get_commit_message_config(panel_provider.context)
2148
if (!api_config) {
2249
if (was_empty_stage) {
23-
await vscode.commands.executeCommand('git.unstageAll')
50+
unstage_changes(repository)
2451
}
2552
panel_provider.send_message({ command: 'COMMIT_PROCESS_CANCELLED' })
2653
return
@@ -35,7 +62,7 @@ async function proceed_with_commit_generation(
3562
dictionary.information_message.NO_CHANGES_TO_COMMIT
3663
)
3764
if (was_empty_stage) {
38-
await vscode.commands.executeCommand('git.unstageAll')
65+
unstage_changes(repository)
3966
}
4067
panel_provider.send_message({ command: 'COMMIT_PROCESS_CANCELLED' })
4168
return
@@ -55,7 +82,7 @@ async function proceed_with_commit_generation(
5582

5683
if (!commit_message) {
5784
if (panel_provider.commit_was_staged_by_script) {
58-
await vscode.commands.executeCommand('git.unstageAll')
85+
unstage_changes(repository)
5986
}
6087
panel_provider.send_message({ command: 'COMMIT_PROCESS_CANCELLED' })
6188
panel_provider.commit_was_staged_by_script = false
@@ -79,7 +106,7 @@ async function proceed_with_commit_generation(
79106
}
80107
} catch (error) {
81108
if (panel_provider.commit_was_staged_by_script) {
82-
await vscode.commands.executeCommand('git.unstageAll')
109+
unstage_changes(repository)
83110
}
84111
panel_provider.send_message({ command: 'COMMIT_PROCESS_CANCELLED' })
85112
panel_provider.commit_was_staged_by_script = false
@@ -99,12 +126,14 @@ export const handle_commit_changes = async (
99126
): Promise<void> => {
100127
await vscode.workspace.saveAll()
101128

102-
const repository = get_git_repository()
129+
const repository = await get_git_repository()
103130
if (!repository) {
104131
panel_provider.send_message({ command: 'COMMIT_PROCESS_CANCELLED' })
105132
return
106133
}
107134

135+
;(panel_provider as any)._selected_repository = repository
136+
108137
await repository.status()
109138

110139
panel_provider.commit_was_staged_by_script = false
@@ -138,12 +167,15 @@ export const handle_proceed_with_commit = async (
138167
panel_provider: PanelProvider,
139168
files_to_stage: string[]
140169
): Promise<void> => {
141-
const repository = get_git_repository()
170+
const repository: GitRepository | undefined = (panel_provider as any)
171+
._selected_repository
142172
if (!repository) {
173+
vscode.window.showErrorMessage(
174+
'No repository selected for committing changes.'
175+
)
143176
panel_provider.send_message({ command: 'COMMIT_PROCESS_CANCELLED' })
144177
return
145178
}
146-
147179
if (files_to_stage.length === 0) {
148180
panel_provider.send_message({ command: 'COMMIT_PROCESS_CANCELLED' })
149181
return

0 commit comments

Comments
 (0)