40
40
#include "add-interactive.h"
41
41
#include "strbuf.h"
42
42
#include "quote.h"
43
+ #include "dir.h"
44
+ #include "entry.h"
43
45
44
46
#define REFRESH_INDEX_DELAY_WARNING_IN_MS (2 * 1000)
45
47
@@ -160,9 +162,48 @@ static void update_index_from_diff(struct diff_queue_struct *q,
160
162
161
163
for (i = 0 ; i < q -> nr ; i ++ ) {
162
164
int pos ;
165
+ int respect_skip_worktree = 1 ;
163
166
struct diff_filespec * one = q -> queue [i ]-> one ;
167
+ struct diff_filespec * two = q -> queue [i ]-> two ;
164
168
int is_in_reset_tree = one -> mode && !is_null_oid (& one -> oid );
169
+ int is_missing = !(one -> mode && !is_null_oid (& one -> oid ));
170
+ int was_missing = !two -> mode && is_null_oid (& two -> oid );
165
171
struct cache_entry * ce ;
172
+ struct cache_entry * ceBefore ;
173
+ struct checkout state = CHECKOUT_INIT ;
174
+
175
+ /*
176
+ * When using the virtual filesystem feature, the cache entries that are
177
+ * added here will not have the skip-worktree bit set.
178
+ *
179
+ * Without this code there is data that is lost because the files that
180
+ * would normally be in the working directory are not there and show as
181
+ * deleted for the next status or in the case of added files just disappear.
182
+ * We need to create the previous version of the files in the working
183
+ * directory so that they will have the right content and the next
184
+ * status call will show modified or untracked files correctly.
185
+ */
186
+ if (core_virtualfilesystem && !file_exists (two -> path ))
187
+ {
188
+ respect_skip_worktree = 0 ;
189
+ pos = index_name_pos (the_repository -> index , two -> path , strlen (two -> path ));
190
+
191
+ if ((pos >= 0 && ce_skip_worktree (the_repository -> index -> cache [pos ])) &&
192
+ (is_missing || !was_missing ))
193
+ {
194
+ state .force = 1 ;
195
+ state .refresh_cache = 1 ;
196
+ state .istate = the_repository -> index ;
197
+ ceBefore = make_cache_entry (the_repository -> index , two -> mode ,
198
+ & two -> oid , two -> path ,
199
+ 0 , 0 );
200
+ if (!ceBefore )
201
+ die (_ ("make_cache_entry failed for path '%s'" ),
202
+ two -> path );
203
+
204
+ checkout_entry (ceBefore , & state , NULL , NULL );
205
+ }
206
+ }
166
207
167
208
if (!is_in_reset_tree && !intent_to_add ) {
168
209
remove_file_from_index (the_repository -> index , one -> path );
@@ -181,8 +222,14 @@ static void update_index_from_diff(struct diff_queue_struct *q,
181
222
* to properly construct the reset sparse directory.
182
223
*/
183
224
pos = index_name_pos (the_repository -> index , one -> path , strlen (one -> path ));
184
- if ((pos >= 0 && ce_skip_worktree (the_repository -> index -> cache [pos ])) ||
185
- (pos < 0 && !path_in_sparse_checkout (one -> path , the_repository -> index )))
225
+
226
+ /*
227
+ * Do not add the SKIP_WORKTREE bit back if we populated the
228
+ * file on purpose in a virtual filesystem scenario.
229
+ */
230
+ if (respect_skip_worktree &&
231
+ ((pos >= 0 && ce_skip_worktree (the_repository -> index -> cache [pos ])) ||
232
+ (pos < 0 && !path_in_sparse_checkout (one -> path , the_repository -> index ))))
186
233
ce -> ce_flags |= CE_SKIP_WORKTREE ;
187
234
188
235
if (!ce )
0 commit comments