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