rev-parse: add --shared-index-path to get shared index path
[gitweb.git] / unpack-trees.c
index ad3e9a04fe8ccb9286b94480f4484b0569f70a57..4a9cdf2105f03f4f615d88155d28984f3fcf50ae 100644 (file)
@@ -8,6 +8,7 @@
 #include "progress.h"
 #include "refs.h"
 #include "attr.h"
+#include "split-index.h"
 
 /*
  * Error messages expected by scripts out of plumbing commands such as
@@ -105,12 +106,11 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
 static void do_add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
                         unsigned int set, unsigned int clear)
 {
-       clear |= CE_HASHED | CE_UNHASHED;
+       clear |= CE_HASHED;
 
        if (set & CE_REMOVE)
                set |= CE_WT_REMOVE;
 
-       ce->next = NULL;
        ce->ce_flags = (ce->ce_flags & ~clear) | set;
        add_index_entry(&o->result, ce,
                        ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
@@ -204,7 +204,7 @@ static int check_updates(struct unpack_trees_options *o)
                                total++;
                }
 
-               progress = start_progress_delay("Checking out files",
+               progress = start_progress_delay(_("Checking out files"),
                                                total, 50, 1);
                cnt = 0;
        }
@@ -247,7 +247,9 @@ static int verify_absent_sparse(const struct cache_entry *ce,
                                enum unpack_trees_error_types,
                                struct unpack_trees_options *o);
 
-static int apply_sparse_checkout(struct cache_entry *ce, struct unpack_trees_options *o)
+static int apply_sparse_checkout(struct index_state *istate,
+                                struct cache_entry *ce,
+                                struct unpack_trees_options *o)
 {
        int was_skip_worktree = ce_skip_worktree(ce);
 
@@ -255,6 +257,10 @@ static int apply_sparse_checkout(struct cache_entry *ce, struct unpack_trees_opt
                ce->ce_flags |= CE_SKIP_WORKTREE;
        else
                ce->ce_flags &= ~CE_SKIP_WORKTREE;
+       if (was_skip_worktree != ce_skip_worktree(ce)) {
+               ce->ce_flags |= CE_UPDATE_IN_BASE;
+               istate->cache_changed |= CE_ENTRY_CHANGED;
+       }
 
        /*
         * if (!was_skip_worktree && !ce_skip_worktree()) {
@@ -830,23 +836,24 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
 }
 
 static int clear_ce_flags_1(struct cache_entry **cache, int nr,
-                           char *prefix, int prefix_len,
+                           struct strbuf *prefix,
                            int select_mask, int clear_mask,
                            struct exclude_list *el, int defval);
 
 /* Whole directory matching */
 static int clear_ce_flags_dir(struct cache_entry **cache, int nr,
-                             char *prefix, int prefix_len,
+                             struct strbuf *prefix,
                              char *basename,
                              int select_mask, int clear_mask,
                              struct exclude_list *el, int defval)
 {
        struct cache_entry **cache_end;
        int dtype = DT_DIR;
-       int ret = is_excluded_from_list(prefix, prefix_len,
+       int ret = is_excluded_from_list(prefix->buf, prefix->len,
                                        basename, &dtype, el);
+       int rc;
 
-       prefix[prefix_len++] = '/';
+       strbuf_addch(prefix, '/');
 
        /* If undecided, use matching result of parent dir in defval */
        if (ret < 0)
@@ -854,7 +861,7 @@ static int clear_ce_flags_dir(struct cache_entry **cache, int nr,
 
        for (cache_end = cache; cache_end != cache + nr; cache_end++) {
                struct cache_entry *ce = *cache_end;
-               if (strncmp(ce->name, prefix, prefix_len))
+               if (strncmp(ce->name, prefix->buf, prefix->len))
                        break;
        }
 
@@ -865,10 +872,12 @@ static int clear_ce_flags_dir(struct cache_entry **cache, int nr,
         * calling clear_ce_flags_1(). That function will call
         * the expensive is_excluded_from_list() on every entry.
         */
-       return clear_ce_flags_1(cache, cache_end - cache,
-                               prefix, prefix_len,
-                               select_mask, clear_mask,
-                               el, ret);
+       rc = clear_ce_flags_1(cache, cache_end - cache,
+                             prefix,
+                             select_mask, clear_mask,
+                             el, ret);
+       strbuf_setlen(prefix, prefix->len - 1);
+       return rc;
 }
 
 /*
@@ -887,7 +896,7 @@ static int clear_ce_flags_dir(struct cache_entry **cache, int nr,
  * Top level path has prefix_len zero.
  */
 static int clear_ce_flags_1(struct cache_entry **cache, int nr,
-                           char *prefix, int prefix_len,
+                           struct strbuf *prefix,
                            int select_mask, int clear_mask,
                            struct exclude_list *el, int defval)
 {
@@ -907,10 +916,10 @@ static int clear_ce_flags_1(struct cache_entry **cache, int nr,
                        continue;
                }
 
-               if (prefix_len && strncmp(ce->name, prefix, prefix_len))
+               if (prefix->len && strncmp(ce->name, prefix->buf, prefix->len))
                        break;
 
-               name = ce->name + prefix_len;
+               name = ce->name + prefix->len;
                slash = strchr(name, '/');
 
                /* If it's a directory, try whole directory match first */
@@ -918,29 +927,26 @@ static int clear_ce_flags_1(struct cache_entry **cache, int nr,
                        int processed;
 
                        len = slash - name;
-                       memcpy(prefix + prefix_len, name, len);
+                       strbuf_add(prefix, name, len);
 
-                       /*
-                        * terminate the string (no trailing slash),
-                        * clear_c_f_dir needs it
-                        */
-                       prefix[prefix_len + len] = '\0';
                        processed = clear_ce_flags_dir(cache, cache_end - cache,
-                                                      prefix, prefix_len + len,
-                                                      prefix + prefix_len,
+                                                      prefix,
+                                                      prefix->buf + prefix->len - len,
                                                       select_mask, clear_mask,
                                                       el, defval);
 
                        /* clear_c_f_dir eats a whole dir already? */
                        if (processed) {
                                cache += processed;
+                               strbuf_setlen(prefix, prefix->len - len);
                                continue;
                        }
 
-                       prefix[prefix_len + len++] = '/';
+                       strbuf_addch(prefix, '/');
                        cache += clear_ce_flags_1(cache, cache_end - cache,
-                                                 prefix, prefix_len + len,
+                                                 prefix,
                                                  select_mask, clear_mask, el, defval);
+                       strbuf_setlen(prefix, prefix->len - len - 1);
                        continue;
                }
 
@@ -961,9 +967,12 @@ static int clear_ce_flags(struct cache_entry **cache, int nr,
                            int select_mask, int clear_mask,
                            struct exclude_list *el)
 {
-       char prefix[PATH_MAX];
+       static struct strbuf prefix = STRBUF_INIT;
+
+       strbuf_reset(&prefix);
+
        return clear_ce_flags_1(cache, nr,
-                               prefix, 0,
+                               &prefix,
                                select_mask, clear_mask,
                                el, 0);
 }
@@ -1023,6 +1032,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
        state.force = 1;
        state.quiet = 1;
        state.refresh_cache = 1;
+       state.istate = &o->result;
 
        memset(&el, 0, sizeof(el));
        if (!core_apply_sparse_checkout || !o->update)
@@ -1039,6 +1049,10 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
        o->result.timestamp.sec = o->src_index->timestamp.sec;
        o->result.timestamp.nsec = o->src_index->timestamp.nsec;
        o->result.version = o->src_index->version;
+       o->result.split_index = o->src_index->split_index;
+       if (o->result.split_index)
+               o->result.split_index->refcount++;
+       hashcpy(o->result.sha1, o->src_index->sha1);
        o->merge_size = len;
        mark_all_ce_unused(o->src_index);
 
@@ -1129,7 +1143,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
                                ret = -1;
                        }
 
-                       if (apply_sparse_checkout(ce, o)) {
+                       if (apply_sparse_checkout(&o->result, ce, o)) {
                                if (!o->show_all_errors)
                                        goto return_failed;
                                ret = -1;
@@ -1257,7 +1271,7 @@ static void invalidate_ce_path(const struct cache_entry *ce,
                               struct unpack_trees_options *o)
 {
        if (ce)
-               cache_tree_invalidate_path(o->src_index->cache_tree, ce->name);
+               cache_tree_invalidate_path(o->src_index, ce->name);
 }
 
 /*