31
#include "revision.h"
32
#include "sequencer.h"
33
#include "setup.h"
34
+#include "sparse-index.h"
35
#include "strvec.h"
36
#include "submodule.h"
37
#include "symlinks.h"
142
return run_hooks_opt(the_repository, "post-checkout", &opt);
143
}
144
145
+/*
146
+ * Handle a tree object and determine if we need to recurse into the
147
+ * tree (READ_TREE_RECURSIVE) or skip it (0).
148
+ */
149
+static int try_update_sparse_directory(const struct object_id *oid,
150
+ struct strbuf *base,
151
+ const char *pathname,
152
+ int overlay_mode)
153
+{
154
+ struct strbuf dirpath = STRBUF_INIT;
155
+ struct cache_entry *old;
156
+ int pos, result = READ_TREE_RECURSIVE;
157
+
158
+ if (!the_repository->index->sparse_index)
159
+ return result;
160
+
161
+ strbuf_addbuf(&dirpath, base);
162
+ strbuf_addstr(&dirpath, pathname);
163
+ strbuf_addch(&dirpath, '/');
164
+
165
+ pos = index_name_pos_sparse(the_repository->index,
166
+ dirpath.buf, dirpath.len);
167
+ if (pos < 0)
168
+ goto cleanup;
169
+
170
+ old = the_repository->index->cache[pos];
171
+ if (!S_ISSPARSEDIR(old->ce_mode))
172
+ goto cleanup;
173
+
174
+ if (oideq(oid, &old->oid)) {
175
+ /* Tree content already matches; no need to descend. */
176
+ result = 0;
177
+ } else if (!overlay_mode) {
178
+ /*
179
+ * In non-overlay mode (e.g., restore --staged), replace the
180
+ * sparse directory OID directly since files not present in
181
+ * the source tree should be removed anyway.
182
+ */
183
+ oidcpy(&old->oid, oid);
184
+ old->ce_flags |= CE_UPDATE;
185
+ result = 0;
186
+ }
187
+
188
+cleanup:
189
+ strbuf_release(&dirpath);
190
+ return result;
191
+}
192
+
193
static int update_some(const struct object_id *oid, struct strbuf *base,
145
- const char *pathname, unsigned mode, void *context UNUSED)
194
+ const char *pathname, unsigned mode, void *context)
195
{
196
int len;
197
struct cache_entry *ce;
198
int pos;
199
+ int overlay_mode = context ? *((int *)context) : 1;
200
201
if (S_ISDIR(mode))
152
- return READ_TREE_RECURSIVE;
202
+ return try_update_sparse_directory(oid, base, pathname,
203
+ overlay_mode);
204
205
len = base->len + strlen(pathname);
206
ce = make_empty_cache_entry(the_repository->index, len);
216
* entry in place. Whether it is UPTODATE or not, checkout_entry will
217
* do the right thing.
218
*/
168
- pos = index_name_pos(the_repository->index, ce->name, ce->ce_namelen);
219
+ pos = index_name_pos_sparse(the_repository->index, ce->name, ce->ce_namelen);
220
if (pos >= 0) {
221
struct cache_entry *old = the_repository->index->cache[pos];
222
if (ce->ce_mode == old->ce_mode &&
233
return 0;
234
}
235
185
-static int read_tree_some(struct tree *tree, const struct pathspec *pathspec)
236
+static int read_tree_some(struct tree *tree, const struct pathspec *pathspec,
237
+ int overlay_mode)
238
{
239
read_tree(the_repository, tree,
188
- pathspec, update_some, NULL);
240
+ pathspec, update_some, &overlay_mode);
241
242
/* update the index with the given tree's info
243
* for all args, expanding wildcards, and exit
632
return error(_("index file corrupt"));
633
634
if (opts->source_tree)
583
- read_tree_some(opts->source_tree, &opts->pathspec);
635
+ read_tree_some(opts->source_tree, &opts->pathspec,
636
+ opts->overlay_mode);
637
if (opts->merge)
638
unmerge_index(the_repository->index, &opts->pathspec, CE_MATCHED);
639