Merge branch 'dt/unpack-save-untracked-cache-extension'
authorJunio C Hamano <gitster@pobox.com>
Tue, 30 May 2017 02:16:45 +0000 (11:16 +0900)
committerJunio C Hamano <gitster@pobox.com>
Tue, 30 May 2017 02:16:45 +0000 (11:16 +0900)
When "git checkout", "git merge", etc. manipulates the in-core
index, various pieces of information in the index extensions are
discarded from the original state, as it is usually not the case
that they are kept up-to-date and in-sync with the operation on the
main index. The untracked cache extension is copied across these
operations now, which would speed up "git status" (as long as the
cache is properly invalidated).

* dt/unpack-save-untracked-cache-extension:
unpack-trees: preserve index extensions

1  2 
cache.h
read-cache.c
unpack-trees.c
diff --combined cache.h
index d1f2c5c08886643f0231945ca27f4d79026a3491,d41336dfd5de9f8fa1486e3d7e41fead87808d6f..ae4c45d379d5b91941616c967a619ae643fe6921
+++ b/cache.h
@@@ -597,6 -597,7 +597,7 @@@ extern int read_index_unmerged(struct i
  #define CLOSE_LOCK            (1 << 1)
  extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags);
  extern int discard_index(struct index_state *);
+ extern void move_index_extensions(struct index_state *dst, struct index_state *src);
  extern int unmerged_index(const struct index_state *);
  extern int verify_path(const char *path);
  extern int strcmp_offset(const char *s1, const char *s2, size_t *first_change);
@@@ -1479,18 -1480,18 +1480,18 @@@ struct date_mode 
  #define DATE_MODE(t) date_mode_from_type(DATE_##t)
  struct date_mode *date_mode_from_type(enum date_mode_type type);
  
 -const char *show_date(unsigned long time, int timezone, const struct date_mode *mode);
 -void show_date_relative(unsigned long time, int tz, const struct timeval *now,
 +const char *show_date(timestamp_t time, int timezone, const struct date_mode *mode);
 +void show_date_relative(timestamp_t time, int tz, const struct timeval *now,
                        struct strbuf *timebuf);
  int parse_date(const char *date, struct strbuf *out);
 -int parse_date_basic(const char *date, unsigned long *timestamp, int *offset);
 -int parse_expiry_date(const char *date, unsigned long *timestamp);
 +int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset);
 +int parse_expiry_date(const char *date, timestamp_t *timestamp);
  void datestamp(struct strbuf *out);
  #define approxidate(s) approxidate_careful((s), NULL)
 -unsigned long approxidate_careful(const char *, int *);
 -unsigned long approxidate_relative(const char *date, const struct timeval *now);
 +timestamp_t approxidate_careful(const char *, int *);
 +timestamp_t approxidate_relative(const char *date, const struct timeval *now);
  void parse_date_format(const char *format, struct date_mode *mode);
 -int date_overflows(unsigned long date);
 +int date_overflows(timestamp_t date);
  
  #define IDENT_STRICT         1
  #define IDENT_NO_DATE        2
@@@ -2198,8 -2199,8 +2199,8 @@@ struct commit_list
  int try_merge_command(const char *strategy, size_t xopts_nr,
                const char **xopts, struct commit_list *common,
                const char *head_arg, struct commit_list *remotes);
 -int checkout_fast_forward(const unsigned char *from,
 -                        const unsigned char *to,
 +int checkout_fast_forward(const struct object_id *from,
 +                        const struct object_id *to,
                          int overwrite_ignore);
  
  
diff --combined read-cache.c
index 22ab8b5b61636cbc3bf8bcaf5a2ef964bf69c4c3,79827a4d71091cf6493a0ed4740cec94c4814b38..92eb15c0004d2a286281fdfb2a489aa45f446288
@@@ -1877,9 -1877,15 +1877,9 @@@ int discard_index(struct index_state *i
  {
        int i;
  
 -      for (i = 0; i < istate->cache_nr; i++) {
 -              if (istate->cache[i]->index &&
 -                  istate->split_index &&
 -                  istate->split_index->base &&
 -                  istate->cache[i]->index <= istate->split_index->base->cache_nr &&
 -                  istate->cache[i] == istate->split_index->base->cache[istate->cache[i]->index - 1])
 -                      continue;
 +      unshare_split_index(istate, 1);
 +      for (i = 0; i < istate->cache_nr; i++)
                free(istate->cache[i]);
 -      }
        resolve_undo_clear_index(istate);
        istate->cache_nr = 0;
        istate->cache_changed = 0;
@@@ -2191,7 -2197,6 +2191,7 @@@ static int do_write_index(struct index_
        int entries = istate->cache_nr;
        struct stat st;
        struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
 +      int drop_cache_tree = 0;
  
        for (i = removed = extended = 0; i < entries; i++) {
                if (cache[i]->ce_flags & CE_REMOVE)
                                warning(msg, ce->name);
                        else
                                return error(msg, ce->name);
 +
 +                      drop_cache_tree = 1;
                }
                if (ce_write_entry(&c, newfd, ce, previous_name) < 0)
                        return -1;
                if (err)
                        return -1;
        }
 -      if (!strip_extensions && istate->cache_tree) {
 +      if (!strip_extensions && !drop_cache_tree && istate->cache_tree) {
                struct strbuf sb = STRBUF_INIT;
  
                cache_tree_write(&sb, istate->cache_tree);
@@@ -2625,3 -2628,9 +2625,9 @@@ void stat_validity_update(struct stat_v
                fill_stat_data(sv->sd, &st);
        }
  }
+ void move_index_extensions(struct index_state *dst, struct index_state *src)
+ {
+       dst->untracked = src->untracked;
+       src->untracked = NULL;
+ }
diff --combined unpack-trees.c
index c312c2cd3affa49b17fad336dce6be89fcc954ba,17117bd0fda83fb2c5fc89082a1d5a72f1049fb8..d38c37e38cf183cf878a9f35b19544d1da0bc438
@@@ -252,18 -252,14 +252,18 @@@ static int check_submodule_move_head(co
                                     const char *new_id,
                                     struct unpack_trees_options *o)
  {
 +      unsigned flags = SUBMODULE_MOVE_HEAD_DRY_RUN;
        const struct submodule *sub = submodule_from_ce(ce);
        if (!sub)
                return 0;
  
 +      if (o->reset)
 +              flags |= SUBMODULE_MOVE_HEAD_FORCE;
 +
        switch (sub->update_strategy.type) {
        case SM_UPDATE_UNSPECIFIED:
        case SM_UPDATE_CHECKOUT:
 -              if (submodule_move_head(ce->name, old_id, new_id, SUBMODULE_MOVE_HEAD_DRY_RUN))
 +              if (submodule_move_head(ce->name, old_id, new_id, flags))
                        return o->gently ? -1 :
                                add_rejected_path(o, ERROR_WOULD_LOSE_SUBMODULE, ce->name);
                return 0;
@@@ -312,7 -308,6 +312,7 @@@ static void unlink_entry(const struct c
                case SM_UPDATE_CHECKOUT:
                case SM_UPDATE_REBASE:
                case SM_UPDATE_MERGE:
 +                      /* state.force is set at the caller. */
                        submodule_move_head(ce->name, "HEAD", NULL,
                                            SUBMODULE_MOVE_HEAD_FORCE);
                        break;
@@@ -1073,7 -1068,7 +1073,7 @@@ static int clear_ce_flags_dir(struct ca
        struct cache_entry **cache_end;
        int dtype = DT_DIR;
        int ret = is_excluded_from_list(prefix->buf, prefix->len,
 -                                      basename, &dtype, el);
 +                                      basename, &dtype, el, &the_index);
        int rc;
  
        strbuf_addch(prefix, '/');
@@@ -1176,7 -1171,7 +1176,7 @@@ static int clear_ce_flags_1(struct cach
                /* Non-directory */
                dtype = ce_to_dtype(ce);
                ret = is_excluded_from_list(ce->name, ce_namelen(ce),
 -                                          name, &dtype, el);
 +                                          name, &dtype, el, &the_index);
                if (ret < 0)
                        ret = defval;
                if (ret > 0)
@@@ -1256,7 -1251,7 +1256,7 @@@ int unpack_trees(unsigned len, struct t
                o->skip_sparse_checkout = 1;
        if (!o->skip_sparse_checkout) {
                char *sparse = git_pathdup("info/sparse-checkout");
 -              if (add_excludes_from_file_to_list(sparse, "", 0, &el, 0) < 0)
 +              if (add_excludes_from_file_to_list(sparse, "", 0, &el, NULL) < 0)
                        o->skip_sparse_checkout = 1;
                else
                        o->el = &el;
                                                  WRITE_TREE_SILENT |
                                                  WRITE_TREE_REPAIR);
                }
+               move_index_extensions(&o->result, o->dst_index);
                discard_index(o->dst_index);
                *o->dst_index = o->result;
        } else {
@@@ -1597,7 -1593,7 +1598,7 @@@ static int verify_clean_subdirectory(co
        memset(&d, 0, sizeof(d));
        if (o->dir)
                d.exclude_per_dir = o->dir->exclude_per_dir;
 -      i = read_directory(&d, pathbuf, namelen+1, NULL);
 +      i = read_directory(&d, &the_index, pathbuf, namelen+1, NULL);
        if (i)
                return o->gently ? -1 :
                        add_rejected_path(o, ERROR_NOT_UPTODATE_DIR, ce->name);
@@@ -1639,7 -1635,7 +1640,7 @@@ static int check_ok_to_remove(const cha
                return 0;
  
        if (o->dir &&
 -          is_excluded(o->dir, name, &dtype))
 +          is_excluded(o->dir, &the_index, name, &dtype))
                /*
                 * ce->name is explicitly excluded, so it is Ok to
                 * overwrite it.