@@ -13,7 +13,6 @@ import { join, relative, resolve } from "./path"
1313import  { 
1414 clearPatchApplicationState , 
1515 getPatchApplicationState , 
16-  PatchState , 
1716 savePatchApplicationState , 
1817}  from  "./stateFile" 
1918
@@ -118,8 +117,8 @@ export function applyPatchesForApp({
118117 ) )  { 
119118 const  state  = 
120119 patches . length  >  1  ? getPatchApplicationState ( patches [ 0 ] )  : null 
121-  let  unappliedPatches  =  patches . slice ( 0 ) 
122-  const  newState :  PatchState [ ]  |   null   =   patches . length   >   1  ?  [ ]  :  null 
120+  const  unappliedPatches  =  patches . slice ( 0 ) 
121+  const  appliedPatches :  PatchedPackageDetails [ ]  =   [ ] 
123122 // if there are multiple patches to apply, we can't rely on the reverse-patch-dry-run behavior to make this operation 
124123 // idempotent, so instead we need to check the state file to see whether we have already applied any of the patches 
125124 // todo: once this is battle tested we might want to use the same approach for single patches as well, but it's not biggie since the dry run thing is fast 
@@ -132,7 +131,7 @@ export function applyPatchesForApp({
132131 ) 
133132 if  ( patchThatWasApplied . patchContentHash  ===  currentPatchHash )  { 
134133 // this patch was applied we can skip it 
135-  unappliedPatches . shift ( ) 
134+  appliedPatches . push ( unappliedPatches . shift ( ) ! ) 
136135 }  else  { 
137136 console . error ( 
138137 chalk . red ( "Error:" ) , 
@@ -144,14 +143,21 @@ export function applyPatchesForApp({
144143 } 
145144 } 
146145
147-  if  ( reverse )  { 
148-  unappliedPatches  =  patches 
149-  . slice ( 0 ,  patches . length  -  unappliedPatches . length ) 
150-  . reverse ( ) 
146+  if  ( reverse  &&  state )  { 
147+  // if we are reversing the patches we need to make the unappliedPatches array 
148+  // be the reversed version of the appliedPatches array. 
149+  // The applied patches array should then be empty because it is used differently 
150+  // when outputting the state file. 
151+  unappliedPatches . length  =  0 
152+  unappliedPatches . push ( ...appliedPatches ) 
153+  unappliedPatches . reverse ( ) 
154+  appliedPatches . length  =  0 
151155 } 
152-  if  ( unappliedPatches . length   ===   0 )  { 
156+  if  ( appliedPatches . length )  { 
153157 // all patches have already been applied 
154-  patches . forEach ( logPatchApplication ) 
158+  appliedPatches . forEach ( logPatchApplication ) 
159+  } 
160+  if  ( ! unappliedPatches . length )  { 
155161 continue 
156162 } 
157163 packageLoop: for  ( const  patchDetails  of  unappliedPatches )  { 
@@ -191,11 +197,7 @@ export function applyPatchesForApp({
191197 cwd : process . cwd ( ) , 
192198 } ) 
193199 )  { 
194-  newState ?. push ( { 
195-  patchFilename, 
196-  patchContentHash : hashFile ( join ( appPath ,  patchDir ,  patchFilename ) ) , 
197-  didApply : true , 
198-  } ) 
200+  appliedPatches . push ( patchDetails ) 
199201 // yay patch was applied successfully 
200202 // print warning if version mismatch 
201203 if  ( installedPackageVersion  !==  version )  { 
@@ -256,11 +258,53 @@ export function applyPatchesForApp({
256258 } 
257259 } 
258260
259-  if  ( newState )  { 
261+  if  ( patches . length   >   1 )  { 
260262 if  ( reverse )  { 
261-  clearPatchApplicationState ( patches [ 0 ] ) 
263+  if  ( ! state )  { 
264+  throw  new  Error ( 
265+  "unexpected state: no state file found while reversing" , 
266+  ) 
267+  } 
268+  // if we removed all the patches that were previously applied we can delete the state file 
269+  if  ( appliedPatches . length  ===  patches . length )  { 
270+  clearPatchApplicationState ( patches [ 0 ] ) 
271+  }  else  { 
272+  // We failed while reversing patches and some are still in the applied state. 
273+  // We need to update the state file to reflect that. 
274+  // appliedPatches is currently the patches that were successfully reversed, in the order they were reversed 
275+  // So we need to find the index of the last reversed patch in the original patches array 
276+  // and then remove all the patches after that. Sorry for the confusing code. 
277+  const  lastReversedPatchIndex  =  patches . indexOf ( 
278+  appliedPatches [ appliedPatches . length  -  1 ] , 
279+  ) 
280+  if  ( lastReversedPatchIndex  ===  - 1 )  { 
281+  throw  new  Error ( 
282+  "unexpected state: failed to find last reversed patch in original patches array" , 
283+  ) 
284+  } 
285+ 
286+  savePatchApplicationState ( 
287+  patches [ 0 ] , 
288+  patches . slice ( 0 ,  lastReversedPatchIndex ) . map ( ( patch )  =>  ( { 
289+  didApply : true , 
290+  patchContentHash : hashFile ( 
291+  join ( appPath ,  patchDir ,  patch . patchFilename ) , 
292+  ) , 
293+  patchFilename : patch . patchFilename , 
294+  } ) ) , 
295+  ) 
296+  } 
262297 }  else  { 
263-  savePatchApplicationState ( patches [ 0 ] ,  newState ) 
298+  savePatchApplicationState ( 
299+  patches [ 0 ] , 
300+  appliedPatches . map ( ( patch )  =>  ( { 
301+  didApply : true , 
302+  patchContentHash : hashFile ( 
303+  join ( appPath ,  patchDir ,  patch . patchFilename ) , 
304+  ) , 
305+  patchFilename : patch . patchFilename , 
306+  } ) ) , 
307+  ) 
264308 } 
265309 } 
266310 } 
0 commit comments