4040#include "add-interactive.h"
4141#include "strbuf.h"
4242#include "quote.h"
43+ #include "dir.h"
44+ #include "entry.h"
4345
4446#define REFRESH_INDEX_DELAY_WARNING_IN_MS (2 * 1000)
4547
@@ -160,9 +162,48 @@ static void update_index_from_diff(struct diff_queue_struct *q,
160162
161163 for (i = 0 ; i < q -> nr ; i ++ ) {
162164 int pos ;
165+ int respect_skip_worktree = 1 ;
163166 struct diff_filespec * one = q -> queue [i ]-> one ;
167+ struct diff_filespec * two = q -> queue [i ]-> two ;
164168 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 );
165171 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+ }
166207
167208 if (!is_in_reset_tree && !intent_to_add ) {
168209 remove_file_from_index (the_repository -> index , one -> path );
@@ -181,8 +222,14 @@ static void update_index_from_diff(struct diff_queue_struct *q,
181222 * to properly construct the reset sparse directory.
182223 */
183224 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 ))))
186233 ce -> ce_flags |= CE_SKIP_WORKTREE ;
187234
188235 if (!ce )
0 commit comments