@@ -23,7 +23,61 @@ class AddLinesConfigurator extends AbstractConfigurator
23
23
self ::POSITION_AFTER_TARGET ,
24
24
];
25
25
26
+ /**
27
+ * Holds file contents for files that have been loaded.
28
+ * This allows us to "change" the contents of a file multiple
29
+ * times before we actually write it out.
30
+ *
31
+ * @var string[]
32
+ */
33
+ private $ fileContents = [];
34
+
26
35
public function configure (Recipe $ recipe , $ config , Lock $ lock , array $ options = []): void
36
+ {
37
+ $ this ->fileContents = [];
38
+ $ this ->executeConfigure ($ recipe , $ config );
39
+
40
+ foreach ($ this ->fileContents as $ file => $ contents ) {
41
+ $ this ->write (sprintf ('[add-lines] Patching file "%s" ' , $ this ->relativize ($ file )));
42
+ file_put_contents ($ file , $ contents );
43
+ }
44
+ }
45
+
46
+ public function unconfigure (Recipe $ recipe , $ config , Lock $ lock ): void
47
+ {
48
+ $ this ->fileContents = [];
49
+ $ this ->executeUnconfigure ($ recipe , $ config );
50
+
51
+ foreach ($ this ->fileContents as $ file => $ change ) {
52
+ $ this ->write (sprintf ('[add-lines] Reverting file "%s" ' , $ this ->relativize ($ file )));
53
+ file_put_contents ($ file , $ change );
54
+ }
55
+ }
56
+
57
+ public function update (RecipeUpdate $ recipeUpdate , array $ originalConfig , array $ newConfig ): void
58
+ {
59
+ // manually check for "requires", as unconfigure ignores it
60
+ $ originalConfig = array_filter ($ originalConfig , function ($ item ) {
61
+ return !isset ($ item ['requires ' ]) || $ this ->isPackageInstalled ($ item ['requires ' ]);
62
+ });
63
+
64
+ // reset the file content cache
65
+ $ this ->fileContents = [];
66
+ $ this ->executeUnconfigure ($ recipeUpdate ->getOriginalRecipe (), $ originalConfig );
67
+ $ this ->executeConfigure ($ recipeUpdate ->getNewRecipe (), $ newConfig );
68
+ $ newFiles = [];
69
+ $ originalFiles = [];
70
+ foreach ($ this ->fileContents as $ file => $ contents ) {
71
+ // set the original file to the current contents
72
+ $ originalFiles [$ this ->relativize ($ file )] = file_get_contents ($ file );
73
+ // and the new file where the old recipe was unconfigured, and the new configured
74
+ $ newFiles [$ this ->relativize ($ file )] = $ contents ;
75
+ }
76
+ $ recipeUpdate ->addOriginalFiles ($ originalFiles );
77
+ $ recipeUpdate ->addNewFiles ($ newFiles );
78
+ }
79
+
80
+ public function executeConfigure (Recipe $ recipe , $ config ): void
27
81
{
28
82
foreach ($ config as $ patch ) {
29
83
if (!isset ($ patch ['file ' ])) {
@@ -57,8 +111,6 @@ public function configure(Recipe $recipe, $config, Lock $lock, array $options =
57
111
continue ;
58
112
}
59
113
60
- $ this ->write (sprintf ('Patching file "%s" ' , $ patch ['file ' ]));
61
-
62
114
if (!isset ($ patch ['position ' ])) {
63
115
$ this ->write (sprintf ('The "position" key is required for the "add-lines" configurator for recipe "%s". Skipping ' , $ recipe ->getName ()));
64
116
@@ -78,11 +130,12 @@ public function configure(Recipe $recipe, $config, Lock $lock, array $options =
78
130
}
79
131
$ target = isset ($ patch ['target ' ]) ? $ patch ['target ' ] : null ;
80
132
81
- $ this ->patchFile ($ file , $ content , $ position , $ target , $ warnIfMissing );
133
+ $ newContents = $ this ->getPatchedContents ($ file , $ content , $ position , $ target , $ warnIfMissing );
134
+ $ this ->fileContents [$ file ] = $ newContents ;
82
135
}
83
136
}
84
137
85
- public function unconfigure (Recipe $ recipe , $ config, Lock $ lock ): void
138
+ public function executeUnconfigure (Recipe $ recipe , $ config ): void
86
139
{
87
140
foreach ($ config as $ patch ) {
88
141
if (!isset ($ patch ['file ' ])) {
@@ -106,51 +159,17 @@ public function unconfigure(Recipe $recipe, $config, Lock $lock): void
106
159
}
107
160
$ value = $ patch ['content ' ];
108
161
109
- $ this ->unPatchFile ($ file , $ value );
162
+ $ newContents = $ this ->getUnPatchedContents ($ file , $ value );
163
+ $ this ->fileContents [$ file ] = $ newContents ;
110
164
}
111
165
}
112
166
113
- public function update ( RecipeUpdate $ recipeUpdate , array $ originalConfig , array $ newConfig ): void
167
+ private function getPatchedContents ( string $ file , string $ value , string $ position , ? string $ target , bool $ warnIfMissing ): string
114
168
{
115
- $ originalConfig = array_filter ($ originalConfig , function ($ item ) {
116
- return !isset ($ item ['requires ' ]) || $ this ->isPackageInstalled ($ item ['requires ' ]);
117
- });
118
- $ newConfig = array_filter ($ newConfig , function ($ item ) {
119
- return !isset ($ item ['requires ' ]) || $ this ->isPackageInstalled ($ item ['requires ' ]);
120
- });
121
-
122
- $ filterDuplicates = function (array $ sourceConfig , array $ comparisonConfig ) {
123
- $ filtered = [];
124
- foreach ($ sourceConfig as $ sourceItem ) {
125
- $ found = false ;
126
- foreach ($ comparisonConfig as $ comparisonItem ) {
127
- if ($ sourceItem ['file ' ] === $ comparisonItem ['file ' ] && $ sourceItem ['content ' ] === $ comparisonItem ['content ' ]) {
128
- $ found = true ;
129
- break ;
130
- }
131
- }
132
- if (!$ found ) {
133
- $ filtered [] = $ sourceItem ;
134
- }
135
- }
136
-
137
- return $ filtered ;
138
- };
139
-
140
- // remove any config where the file+value is the same before & after
141
- $ filteredOriginalConfig = $ filterDuplicates ($ originalConfig , $ newConfig );
142
- $ filteredNewConfig = $ filterDuplicates ($ newConfig , $ originalConfig );
143
-
144
- $ this ->unconfigure ($ recipeUpdate ->getOriginalRecipe (), $ filteredOriginalConfig , $ recipeUpdate ->getLock ());
145
- $ this ->configure ($ recipeUpdate ->getNewRecipe (), $ filteredNewConfig , $ recipeUpdate ->getLock ());
146
- }
147
-
148
- private function patchFile (string $ file , string $ value , string $ position , ?string $ target , bool $ warnIfMissing )
149
- {
150
- $ fileContents = file_get_contents ($ file );
169
+ $ fileContents = $ this ->readFile ($ file );
151
170
152
171
if (false !== strpos ($ fileContents , $ value )) {
153
- return ; // already includes value, skip
172
+ return $ fileContents ; // already includes value, skip
154
173
}
155
174
156
175
switch ($ position ) {
@@ -188,15 +207,15 @@ private function patchFile(string $file, string $value, string $position, ?strin
188
207
break ;
189
208
}
190
209
191
- file_put_contents ( $ file , $ fileContents) ;
210
+ return $ fileContents ;
192
211
}
193
212
194
- private function unPatchFile (string $ file , $ value )
213
+ private function getUnPatchedContents (string $ file , $ value ): string
195
214
{
196
- $ fileContents = file_get_contents ($ file );
215
+ $ fileContents = $ this -> readFile ($ file );
197
216
198
217
if (false === strpos ($ fileContents , $ value )) {
199
- return ; // value already gone!
218
+ return $ fileContents ; // value already gone!
200
219
}
201
220
202
221
if (false !== strpos ($ fileContents , "\n" .$ value )) {
@@ -206,9 +225,8 @@ private function unPatchFile(string $file, $value)
206
225
}
207
226
208
227
$ position = strpos ($ fileContents , $ value );
209
- $ fileContents = substr_replace ($ fileContents , '' , $ position , \strlen ($ value ));
210
228
211
- file_put_contents ( $ file , $ fileContents );
229
+ return substr_replace ( $ fileContents , '' , $ position , \strlen ( $ value ) );
212
230
}
213
231
214
232
private function isPackageInstalled ($ packages ): bool
@@ -227,4 +245,26 @@ private function isPackageInstalled($packages): bool
227
245
228
246
return true ;
229
247
}
248
+
249
+ private function relativize (string $ path ): string
250
+ {
251
+ $ rootDir = $ this ->options ->get ('root-dir ' );
252
+ if (0 === strpos ($ path , $ rootDir )) {
253
+ $ path = substr ($ path , \strlen ($ rootDir ) + 1 );
254
+ }
255
+
256
+ return ltrim ($ path , '/ \\' );
257
+ }
258
+
259
+ private function readFile (string $ file ): string
260
+ {
261
+ if (isset ($ this ->fileContents [$ file ])) {
262
+ return $ this ->fileContents [$ file ];
263
+ }
264
+
265
+ $ fileContents = file_get_contents ($ file );
266
+ $ this ->fileContents [$ file ] = $ fileContents ;
267
+
268
+ return $ fileContents ;
269
+ }
230
270
}
0 commit comments