@@ -3,14 +3,17 @@ import { ProviderSettingsManager } from "../../core/config/ProviderSettingsManag
33import { t } from "../../i18n"
44import { Package } from "../../shared/package"
55
6- import { CommitMessageRequest , CommitMessageResult } from "./types/core"
76import { CommitMessageGenerator } from "./CommitMessageGenerator"
8- import { VSCodeCommitMessageAdapter } from "./adapters/VSCodeCommitMessageAdapter"
9- import { VscGenerationRequest } from "./types"
7+ import { GitExtensionService } from "./GitExtensionService"
8+ import { GitChange } from "./types"
9+
10+ interface VscGenerationRequest {
11+ inputBox : { value : string }
12+ rootUri ?: vscode . Uri
13+ }
1014
1115export class CommitMessageProvider implements vscode . Disposable {
1216 private generator : CommitMessageGenerator
13- private vscodeAdapter : VSCodeCommitMessageAdapter
1417
1518 constructor (
1619 private context : vscode . ExtensionContext ,
@@ -19,7 +22,6 @@ export class CommitMessageProvider implements vscode.Disposable {
1922 const providerSettingsManager = new ProviderSettingsManager ( this . context )
2023
2124 this . generator = new CommitMessageGenerator ( providerSettingsManager )
22- this . vscodeAdapter = new VSCodeCommitMessageAdapter ( this . generator )
2325 }
2426
2527 public async activate ( ) : Promise < void > {
@@ -35,11 +37,125 @@ export class CommitMessageProvider implements vscode.Disposable {
3537 }
3638
3739 private async handleVSCodeCommand ( vsRequest ?: VscGenerationRequest ) : Promise < void > {
38- const request : CommitMessageRequest = {
39- workspacePath : this . determineWorkspacePath ( vsRequest ?. rootUri ) ,
40+ try {
41+ const workspacePath = this . determineWorkspacePath ( vsRequest ?. rootUri )
42+ const targetRepository = await this . determineTargetRepository ( workspacePath )
43+ if ( ! targetRepository ?. rootUri ) {
44+ throw new Error ( "Could not determine Git repository" )
45+ }
46+
47+ await vscode . window . withProgress (
48+ {
49+ location : vscode . ProgressLocation . SourceControl ,
50+ title : t ( "common:commitMessage.generating" ) ,
51+ cancellable : false ,
52+ } ,
53+ async ( progress ) => {
54+ let lastPercentage = 0
55+ const reportProgress = ( percentage : number , message ?: string ) => {
56+ progress . report ( {
57+ increment : Math . max ( 0 , percentage - lastPercentage ) ,
58+ message : message || t ( "common:commitMessage.generating" ) ,
59+ } )
60+ lastPercentage = percentage
61+ }
62+
63+ reportProgress ( 5 , t ( "common:commitMessage.initializing" ) )
64+ const gitService = new GitExtensionService ( workspacePath )
65+
66+ try {
67+ reportProgress ( 15 , t ( "common:commitMessage.discoveringFiles" ) )
68+ const resolution = await this . resolveCommitChanges ( gitService )
69+
70+ if ( resolution . changes . length === 0 ) {
71+ vscode . window . showInformationMessage ( t ( "common:commitMessage.noChanges" ) )
72+ return
73+ }
74+
75+ reportProgress ( 25 , t ( "common:commitMessage.foundChanges" , { count : resolution . changes . length } ) )
76+
77+ if ( ! resolution . usedStaged ) {
78+ vscode . window . showInformationMessage ( t ( "common:commitMessage.generatingFromUnstaged" ) )
79+ }
80+
81+ reportProgress ( 40 , t ( "common:commitMessage.gettingContext" ) )
82+ const gitContext = await gitService . getCommitContext (
83+ resolution . changes ,
84+ { staged : resolution . usedStaged , includeRepoContext : true } ,
85+ resolution . files ,
86+ )
87+
88+ reportProgress ( 70 , t ( "common:commitMessage.generating" ) )
89+ const message = await this . generator . generateMessage ( {
90+ workspacePath,
91+ selectedFiles : resolution . files ,
92+ gitContext,
93+ onProgress : ( update ) => {
94+ if ( update . percentage !== undefined ) {
95+ reportProgress ( 70 + update . percentage * 0.25 , update . message )
96+ }
97+ } ,
98+ } )
99+
100+ targetRepository . inputBox . value = message
101+ reportProgress ( 100 , t ( "common:commitMessage.generated" ) )
102+ } finally {
103+ gitService . dispose ( )
104+ }
105+ } ,
106+ )
107+ } catch ( error ) {
108+ const errorMessage = error instanceof Error ? error . message : "Unknown error occurred"
109+ vscode . window . showErrorMessage ( t ( "common:commitMessage.generationFailed" , { errorMessage } ) )
110+ }
111+ }
112+
113+ private async resolveCommitChanges ( gitService : GitExtensionService ) : Promise < {
114+ changes : GitChange [ ]
115+ files : string [ ]
116+ usedStaged : boolean
117+ } > {
118+ let changes = await gitService . gatherChanges ( { staged : true } )
119+ let usedStaged = true
120+
121+ if ( changes . length === 0 ) {
122+ changes = await gitService . gatherChanges ( { staged : false } )
123+ usedStaged = false
40124 }
41125
42- await this . vscodeAdapter . generateCommitMessage ( request )
126+ return {
127+ changes,
128+ files : changes . map ( ( change ) => change . filePath ) ,
129+ usedStaged,
130+ }
131+ }
132+
133+ private async determineTargetRepository ( workspacePath : string ) : Promise < VscGenerationRequest | null > {
134+ try {
135+ const gitExtension = vscode . extensions . getExtension ( "vscode.git" )
136+ if ( ! gitExtension ) {
137+ return null
138+ }
139+
140+ if ( ! gitExtension . isActive ) {
141+ await gitExtension . activate ( )
142+ }
143+
144+ const gitApi = gitExtension . exports . getAPI ( 1 )
145+ if ( ! gitApi ) {
146+ return null
147+ }
148+
149+ for ( const repo of gitApi . repositories ?? [ ] ) {
150+ if ( repo . rootUri && workspacePath . startsWith ( repo . rootUri . fsPath ) ) {
151+ return repo
152+ }
153+ }
154+
155+ return gitApi . repositories [ 0 ] ?? null
156+ } catch ( error ) {
157+ return null
158+ }
43159 }
44160
45161 private determineWorkspacePath ( resourceUri ?: vscode . Uri ) : string {
@@ -55,7 +171,5 @@ export class CommitMessageProvider implements vscode.Disposable {
55171 throw new Error ( "Could not determine workspace path" )
56172 }
57173
58- public dispose ( ) : void {
59- this . vscodeAdapter ?. dispose ( )
60- }
174+ public dispose ( ) : void { }
61175}
0 commit comments