1- import type { GitBranch } from '../../../git/models/branch' ;
2- import type { GitCommit } from '../../../git/models/commit' ;
1+ import { sha256 } from '@env/crypto' ;
32import type { GitDiff , ParsedGitDiff } from '../../../git/models/diff' ;
43import type { Repository } from '../../../git/models/repository' ;
54import { uncommitted , uncommittedStaged } from '../../../git/models/revision' ;
@@ -336,36 +335,20 @@ export async function getWorkingTreeDiffs(repo: Repository): Promise<WorkingTree
336335export async function createSafetyState (
337336 repo : Repository ,
338337 diffs : WorkingTreeDiffs ,
339- currentBranch : GitBranch ,
340- headCommit : GitCommit ,
338+ headSha : string ,
341339) : Promise < ComposerSafetyState > {
342- // Get current worktree information
343- const worktrees = await repo . git . worktrees ?. getWorktrees ( ) ;
344- const currentWorktree = worktrees ?. find ( wt => wt . branch ?. id === currentBranch ?. id ) ;
345-
346- if ( ! currentBranch ?. name ) {
347- throw new Error ( 'Cannot create safety state: no current branch found' ) ;
348- }
349- if ( ! currentBranch ?. sha ) {
350- throw new Error ( 'Cannot create safety state: no current branch SHA found' ) ;
351- }
352- if ( ! headCommit ?. sha ) {
340+ if ( ! headSha ) {
353341 throw new Error ( 'Cannot create safety state: no HEAD commit found' ) ;
354342 }
355- if ( ! currentWorktree ?. name ) {
356- throw new Error ( 'Cannot create safety state: no current worktree found' ) ;
357- }
358343
359344 return {
360345 repoPath : repo . path ,
361- headSha : headCommit . sha ,
362- branchName : currentBranch . name ,
363- branchRefSha : currentBranch . sha ,
364- worktreeName : currentWorktree . name ,
365- stagedDiff : diffs . staged ?. contents ?? null ,
366- unstagedDiff : diffs . unstaged ?. contents ?? null ,
367- unifiedDiff : diffs . unified ?. contents ?? null ,
368- timestamp : Date . now ( ) ,
346+ headSha : headSha ,
347+ hashes : {
348+ staged : diffs . staged ?. contents ? await sha256 ( diffs . staged . contents ) : null ,
349+ unstaged : diffs . unstaged ?. contents ? await sha256 ( diffs . unstaged . contents ) : null ,
350+ unified : diffs . unified ?. contents ? await sha256 ( diffs . unified . contents ) : null ,
351+ } ,
369352 } ;
370353}
371354
@@ -393,44 +376,25 @@ export async function validateSafetyState(
393376 errors . push ( `HEAD commit changed from "${ safetyState . headSha } " to "${ currentHeadSha } "` ) ;
394377 }
395378
396- // 3. Check current branch
397- const currentBranch = await repo . git . branches . getBranch ( ) ;
398- const currentBranchName = currentBranch ?. name ;
399- if ( ! currentBranchName ) {
400- errors . push ( 'Current branch could not be determined' ) ;
401- } else if ( currentBranchName !== safetyState . branchName ) {
402- errors . push ( `Branch changed from "${ safetyState . branchName } " to "${ currentBranchName } "` ) ;
403- }
404-
405- // 4. Check branch ref SHA
406- const currentBranchSha = currentBranch ?. sha ;
407- if ( ! currentBranchSha ) {
408- errors . push ( 'Current branch SHA could not be determined' ) ;
409- } else if ( currentBranchSha !== safetyState . branchRefSha ) {
410- errors . push ( `Branch ref changed from "${ safetyState . branchRefSha } " to "${ currentBranchSha } "` ) ;
411- }
379+ // 2. Smart diff validation - only check diffs for sources being committed
380+ if ( hunksBeingCommitted ?. length ) {
381+ const { staged, unstaged /*, unified*/ } = await getWorkingTreeDiffs ( repo ) ;
412382
413- // 5. Check worktree state
414- const worktrees = await repo . git . worktrees ?. getWorktrees ( ) ;
415- const currentWorktree = worktrees ?. find ( wt => wt . branch ?. id === currentBranch ?. id ) ;
416- const currentWorktreeName = currentWorktree ?. name ?? 'main' ;
417- if ( currentWorktreeName !== safetyState . worktreeName ) {
418- errors . push ( `Worktree changed from "${ safetyState . worktreeName } " to "${ currentWorktreeName } "` ) ;
419- }
420-
421- // 6. Smart diff validation - only check diffs for sources being committed
422- if ( hunksBeingCommitted && hunksBeingCommitted . length > 0 ) {
423- const { staged, unstaged } = await getWorkingTreeDiffs ( repo ) ;
383+ const hashes = {
384+ staged : staged ?. contents ? await sha256 ( staged . contents ) : null ,
385+ unstaged : unstaged ?. contents ? await sha256 ( unstaged . contents ) : null ,
386+ // unified: unified?.contents ? await sha256(unified.contents) : null,
387+ } ;
424388
425389 // Check if any hunks from staged source are being committed
426390 const hasStagedHunks = hunksBeingCommitted . some ( h => h . source === 'staged' ) ;
427- if ( hasStagedHunks && ( staged ?. contents ?? null ) !== safetyState . stagedDiff ) {
391+ if ( hasStagedHunks && hashes . staged !== safetyState . hashes . staged ) {
428392 errors . push ( 'Staged changes have been modified since composer opened' ) ;
429393 }
430394
431395 // Check if any hunks from unstaged source are being committed
432396 const hasUnstagedHunks = hunksBeingCommitted . some ( h => h . source === 'unstaged' ) ;
433- if ( hasUnstagedHunks && ( unstaged ?. contents ?? null ) !== safetyState . unstagedDiff ) {
397+ if ( hasUnstagedHunks && hashes . unstaged !== safetyState . hashes . unstaged ) {
434398 errors . push ( 'Unstaged changes have been modified since composer opened' ) ;
435399 }
436400 }
@@ -442,21 +406,12 @@ export async function validateSafetyState(
442406 }
443407}
444408
445- /** Validates combined output diff against input diff, based on whether unstaged changes are included or not */
446- export function validateCombinedDiff (
409+ /** Validates resulting output diff against input diff, based on whether unstaged changes are included or not */
410+ export function validateResultingDiff (
447411 safetyState : ComposerSafetyState ,
448- combinedDiff : string ,
412+ diffHash : string ,
449413 includeUnstagedChanges : boolean ,
450414) : boolean {
451- try {
452- const { stagedDiff, unifiedDiff } = safetyState ;
453-
454- if ( includeUnstagedChanges ) {
455- return combinedDiff === unifiedDiff ;
456- }
457-
458- return combinedDiff === stagedDiff ;
459- } catch {
460- return false ;
461- }
415+ const { hashes } = safetyState ;
416+ return diffHash === ( includeUnstagedChanges ? hashes . unified : hashes . staged ) ;
462417}
0 commit comments