@@ -22,6 +22,7 @@ import { response_preview_promise_resolve } from '../../apply-chat-response-comm
2222import { ongoing_review_cleanup_promise } from '../../apply-chat-response-command/utils/preview-handler'
2323import { dictionary } from '@shared/constants/dictionary'
2424import { WebsitesProvider } from '@/context/providers/websites-provider'
25+ import { get_git_info } from '../utils/git-utils'
2526
2627export const restore_checkpoint = async ( params : {
2728 checkpoint : Checkpoint
@@ -163,6 +164,118 @@ export const restore_checkpoint = async (params: {
163164 const git_info = params . checkpoint . git_data [ folder_name ]
164165
165166 if ( git_info ) {
167+ const current_git_info = await get_git_info ( folder )
168+ if (
169+ current_git_info &&
170+ current_git_info . commit_hash == git_info . commit_hash
171+ ) {
172+ // OPTIMIZED PATH: Same commit hash. Reject changes and apply diff.
173+ try {
174+ // Discard changes in tracked files
175+ execSync ( `git restore .` , {
176+ cwd : folder . uri . fsPath ,
177+ stdio : 'pipe'
178+ } )
179+ // Remove untracked files
180+ execSync ( `git clean -fd` , {
181+ cwd : folder . uri . fsPath ,
182+ stdio : 'pipe'
183+ } )
184+ } catch ( error ) {
185+ Logger . warn ( {
186+ function_name : 'restore_checkpoint' ,
187+ message : `git restore/clean failed for ${ folder . name } , falling back to checkout` ,
188+ data : error
189+ } )
190+ try {
191+ execSync ( `git checkout .` , {
192+ cwd : folder . uri . fsPath ,
193+ stdio : 'pipe'
194+ } )
195+ execSync ( `git clean -fd` , {
196+ cwd : folder . uri . fsPath ,
197+ stdio : 'pipe'
198+ } )
199+ } catch ( e ) {
200+ Logger . error ( {
201+ function_name : 'restore_checkpoint' ,
202+ message : `Failed to reject changes for ${ folder . name } ` ,
203+ data : e
204+ } )
205+ throw new Error (
206+ `Failed to reject changes for ${ folder . name } . Please ensure your git working directory is clean.`
207+ )
208+ }
209+ }
210+
211+ const diff_file_path = path . join (
212+ checkpoint_dir_path ,
213+ `${ folder_name } .diff`
214+ )
215+
216+ let diff = ''
217+ try {
218+ const diff_content = await vscode . workspace . fs . readFile (
219+ vscode . Uri . file ( diff_file_path )
220+ )
221+ diff = Buffer . from ( diff_content ) . toString ( 'utf8' )
222+ } catch ( e ) {
223+ // diff file might not exist if there were no changes.
224+ }
225+
226+ if ( diff . trim ( ) . length > 0 ) {
227+ const temp_diff_path = path . join (
228+ os . tmpdir ( ) ,
229+ `cwc-diff-${ Date . now ( ) } -${ Math . random ( )
230+ . toString ( )
231+ . slice ( 2 ) } .diff`
232+ )
233+
234+ await vscode . workspace . fs . writeFile (
235+ vscode . Uri . file ( temp_diff_path ) ,
236+ Buffer . from ( diff , 'utf8' )
237+ )
238+ try {
239+ execSync (
240+ `git apply --whitespace=nowarn "${ temp_diff_path } "` ,
241+ {
242+ cwd : folder . uri . fsPath ,
243+ stdio : 'pipe'
244+ }
245+ )
246+ } catch ( e ) {
247+ try {
248+ execSync (
249+ `git apply --reject --whitespace=nowarn "${ temp_diff_path } "` ,
250+ {
251+ cwd : folder . uri . fsPath ,
252+ stdio : 'pipe'
253+ }
254+ )
255+ vscode . window . showWarningMessage (
256+ `Some changes for ${ folder . name } could not be applied cleanly during checkpoint restore. Check for .rej files in your workspace.`
257+ )
258+ } catch ( rejectErr ) {
259+ Logger . error ( {
260+ function_name : 'restore_checkpoint' ,
261+ message : `Failed to apply git diff even with --reject for ${ folder . name } ` ,
262+ data : rejectErr
263+ } )
264+ throw new Error (
265+ `Failed to apply git diff for ${ folder . name } `
266+ )
267+ }
268+ } finally {
269+ try {
270+ await vscode . workspace . fs . delete (
271+ vscode . Uri . file ( temp_diff_path )
272+ )
273+ } catch { }
274+ }
275+ }
276+ continue // Continue to next folder
277+ }
278+
166279 const temp_git_clone_path = path . join (
167280 os . tmpdir ( ) ,
168281 `cwc-git-clone-${ Date . now ( ) } -${ Math . random ( ) . toString ( ) . slice ( 2 ) } `
0 commit comments