Skip to content

Commit 0203f7f

Browse files
committed
Refactor Git checkpoint restoration to include an optimized path that uses git restore and git apply for faster restoration when the current commit hash matches the checkpoint's base commit
1 parent 9c1f882 commit 0203f7f

1 file changed

Lines changed: 113 additions & 0 deletions

File tree

‎packages/vscode/src/commands/checkpoints-command/actions/restore-checkpoint.ts‎

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { response_preview_promise_resolve } from '../../apply-chat-response-comm
2222
import { ongoing_review_cleanup_promise } from '../../apply-chat-response-command/utils/preview-handler'
2323
import { dictionary } from '@shared/constants/dictionary'
2424
import { WebsitesProvider } from '@/context/providers/websites-provider'
25+
import { get_git_info } from '../utils/git-utils'
2526

2627
export 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

Comments
 (0)