@@ -38,56 +38,37 @@ public function __construct(string $rootDir, IOInterface $io)
38
38
*/
39
39
public function applyPatch (RecipePatch $ patch ): bool
40
40
{
41
- if (!$ patch ->getPatch ()) {
42
- // nothing to do!
43
- return true ;
44
- }
45
-
46
- $ addedBlobs = $ this ->addMissingBlobs ($ patch ->getBlobs ());
47
-
48
- $ patchPath = $ this ->rootDir .'/_flex_recipe_update.patch ' ;
49
- file_put_contents ($ patchPath , $ patch ->getPatch ());
50
-
51
- try {
52
- $ this ->execute ('git update-index --refresh ' , $ this ->rootDir );
53
-
54
- $ output = '' ;
55
- $ statusCode = $ this ->processExecutor ->execute ('git apply "_flex_recipe_update.patch" -3 ' , $ output , $ this ->rootDir );
41
+ $ withConflicts = $ this ->_applyPatchFile ($ patch );
56
42
57
- if (0 === $ statusCode ) {
58
- // successful with no conflicts
59
- return true ;
60
- }
61
-
62
- if (false !== strpos ($ this ->processExecutor ->getErrorOutput (), 'with conflicts ' )) {
63
- // successful with conflicts
64
- return false ;
65
- }
66
-
67
- throw new \LogicException ('Error applying the patch: ' .$ this ->processExecutor ->getErrorOutput ());
68
- } finally {
69
- unlink ($ patchPath );
70
- // clean up any temporary blobs
71
- foreach ($ addedBlobs as $ filename ) {
72
- unlink ($ filename );
43
+ foreach ($ patch ->getDeletedFiles () as $ deletedFile ) {
44
+ if (file_exists ($ this ->rootDir .'/ ' .$ deletedFile )) {
45
+ $ this ->execute (sprintf ('git rm %s ' , ProcessExecutor::escape ($ deletedFile )), $ this ->rootDir );
73
46
}
74
47
}
48
+
49
+ return $ withConflicts ;
75
50
}
76
51
77
52
public function generatePatch (array $ originalFiles , array $ newFiles ): RecipePatch
78
53
{
54
+ $ ignoredFiles = $ this ->getIgnoredFiles (array_keys ($ originalFiles ) + array_keys ($ newFiles ));
55
+
79
56
// null implies "file does not exist"
80
- $ originalFiles = array_filter ($ originalFiles , function ($ file ) {
81
- return null !== $ file ;
82
- });
83
- $ newFiles = array_filter ($ newFiles , function ($ file ) {
84
- return null !== $ file ;
85
- });
86
-
87
- // find removed files and add them so they will be deleted
57
+ $ originalFiles = array_filter ($ originalFiles , function ($ file , $ fileName ) use ($ ignoredFiles ) {
58
+ return null !== $ file && !\in_array ($ fileName , $ ignoredFiles );
59
+ }, \ARRAY_FILTER_USE_BOTH );
60
+
61
+ $ newFiles = array_filter ($ newFiles , function ($ file , $ fileName ) use ($ ignoredFiles ) {
62
+ return null !== $ file && !\in_array ($ fileName , $ ignoredFiles );
63
+ }, \ARRAY_FILTER_USE_BOTH );
64
+
65
+ $ deletedFiles = [];
66
+ // find removed files & record that they are deleted
67
+ // unset them from originalFiles to avoid unnecessary blobs being added
88
68
foreach ($ originalFiles as $ file => $ contents ) {
89
69
if (!isset ($ newFiles [$ file ])) {
90
- $ newFiles [$ file ] = null ;
70
+ $ deletedFiles [] = $ file ;
71
+ unset($ originalFiles [$ file ]);
91
72
}
92
73
}
93
74
@@ -130,6 +111,7 @@ public function generatePatch(array $originalFiles, array $newFiles): RecipePatc
130
111
return new RecipePatch (
131
112
$ patchString ,
132
113
$ blobs ,
114
+ $ deletedFiles ,
133
115
$ removedPatches
134
116
);
135
117
} finally {
@@ -223,4 +205,51 @@ private function getBlobPath(string $hash): string
223
205
224
206
return '.git/objects/ ' .$ hashStart .'/ ' .$ hashEnd ;
225
207
}
208
+
209
+ private function _applyPatchFile (RecipePatch $ patch )
210
+ {
211
+ if (!$ patch ->getPatch ()) {
212
+ // nothing to do!
213
+ return true ;
214
+ }
215
+
216
+ $ addedBlobs = $ this ->addMissingBlobs ($ patch ->getBlobs ());
217
+
218
+ $ patchPath = $ this ->rootDir .'/_flex_recipe_update.patch ' ;
219
+ file_put_contents ($ patchPath , $ patch ->getPatch ());
220
+
221
+ try {
222
+ $ this ->execute ('git update-index --refresh ' , $ this ->rootDir );
223
+
224
+ $ output = '' ;
225
+ $ statusCode = $ this ->processExecutor ->execute ('git apply "_flex_recipe_update.patch" -3 ' , $ output , $ this ->rootDir );
226
+
227
+ if (0 === $ statusCode ) {
228
+ // successful with no conflicts
229
+ return true ;
230
+ }
231
+
232
+ if (false !== strpos ($ this ->processExecutor ->getErrorOutput (), 'with conflicts ' )) {
233
+ // successful with conflicts
234
+ return false ;
235
+ }
236
+
237
+ throw new \LogicException ('Error applying the patch: ' .$ this ->processExecutor ->getErrorOutput ());
238
+ } finally {
239
+ unlink ($ patchPath );
240
+ // clean up any temporary blobs
241
+ foreach ($ addedBlobs as $ filename ) {
242
+ unlink ($ filename );
243
+ }
244
+ }
245
+ }
246
+
247
+ private function getIgnoredFiles (array $ fileNames ): array
248
+ {
249
+ $ args = implode (' ' , array_map ([ProcessExecutor::class, 'escape ' ], $ fileNames ));
250
+ $ output = '' ;
251
+ $ this ->processExecutor ->execute (sprintf ('git check-ignore %s ' , $ args ), $ output , $ this ->rootDir );
252
+
253
+ return $ this ->processExecutor ->splitLines ($ output );
254
+ }
226
255
}
0 commit comments