Merge branch 'nd/reset-intent-to-add'
authorJunio C Hamano <gitster@pobox.com>
Thu, 27 Feb 2014 22:01:40 +0000 (14:01 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 27 Feb 2014 22:01:40 +0000 (14:01 -0800)
* nd/reset-intent-to-add:
reset: support "--mixed --intent-to-add" mode

1  2 
cache.h
read-cache.c
diff --combined cache.h
index 5994f7a2034268ce4f69afc5e99aafe7586ccef7,8f35d12a7ef78f8651d2ec2701189113246caebb..9f1574421816bfde4236447d1d799c56cbed1671
+++ b/cache.h
@@@ -3,7 -3,7 +3,7 @@@
  
  #include "git-compat-util.h"
  #include "strbuf.h"
 -#include "hash.h"
 +#include "hashmap.h"
  #include "advice.h"
  #include "gettext.h"
  #include "convert.h"
@@@ -130,12 -130,12 +130,12 @@@ struct stat_data 
  };
  
  struct cache_entry {
 +      struct hashmap_entry ent;
        struct stat_data ce_stat_data;
        unsigned int ce_mode;
        unsigned int ce_flags;
        unsigned int ce_namelen;
        unsigned char sha1[20];
 -      struct cache_entry *next;
        char name[FLEX_ARRAY]; /* more */
  };
  
  #define CE_ADDED             (1 << 19)
  
  #define CE_HASHED            (1 << 20)
 -#define CE_UNHASHED          (1 << 21)
  #define CE_WT_REMOVE         (1 << 22) /* remove in work directory */
  #define CE_CONFLICTED        (1 << 23)
  
@@@ -194,18 -195,17 +194,18 @@@ struct pathspec
   * Copy the sha1 and stat state of a cache entry from one to
   * another. But we never change the name, or the hash state!
   */
 -#define CE_STATE_MASK (CE_HASHED | CE_UNHASHED)
  static inline void copy_cache_entry(struct cache_entry *dst,
                                    const struct cache_entry *src)
  {
 -      unsigned int state = dst->ce_flags & CE_STATE_MASK;
 +      unsigned int state = dst->ce_flags & CE_HASHED;
  
        /* Don't copy hash chain and name */
 -      memcpy(dst, src, offsetof(struct cache_entry, next));
 +      memcpy(&dst->ce_stat_data, &src->ce_stat_data,
 +                      offsetof(struct cache_entry, name) -
 +                      offsetof(struct cache_entry, ce_stat_data));
  
        /* Restore the hash state */
 -      dst->ce_flags = (dst->ce_flags & ~CE_STATE_MASK) | state;
 +      dst->ce_flags = (dst->ce_flags & ~CE_HASHED) | state;
  }
  
  static inline unsigned create_ce_flags(unsigned stage)
@@@ -277,8 -277,8 +277,8 @@@ struct index_state 
        struct cache_time timestamp;
        unsigned name_hash_initialized : 1,
                 initialized : 1;
 -      struct hash_table name_hash;
 -      struct hash_table dir_hash;
 +      struct hashmap name_hash;
 +      struct hashmap dir_hash;
  };
  
  extern struct index_state the_index;
@@@ -316,6 -316,7 +316,6 @@@ extern void free_name_hash(struct index
  #define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))
  #define cache_dir_exists(name, namelen) index_dir_exists(&the_index, (name), (namelen))
  #define cache_file_exists(name, namelen, igncase) index_file_exists(&the_index, (name), (namelen), (igncase))
 -#define cache_name_exists(name, namelen, igncase) index_name_exists(&the_index, (name), (namelen), (igncase))
  #define cache_name_is_other(name, namelen) index_name_is_other(&the_index, (name), (namelen))
  #define resolve_undo_clear() resolve_undo_clear_index(&the_index)
  #define unmerge_cache_entry_at(at) unmerge_index_entry_at(&the_index, at)
@@@ -466,6 -467,7 +466,6 @@@ extern int unmerged_index(const struct 
  extern int verify_path(const char *path);
  extern struct cache_entry *index_dir_exists(struct index_state *istate, const char *name, int namelen);
  extern struct cache_entry *index_file_exists(struct index_state *istate, const char *name, int namelen, int igncase);
 -extern struct cache_entry *index_name_exists(struct index_state *istate, const char *name, int namelen, int igncase);
  extern int index_name_pos(const struct index_state *, const char *name, int namelen);
  #define ADD_CACHE_OK_TO_ADD 1         /* Ok to add */
  #define ADD_CACHE_OK_TO_REPLACE 2     /* Ok to replace file/directory */
@@@ -485,8 -487,9 +485,9 @@@ extern int remove_file_from_index(struc
  #define ADD_CACHE_IMPLICIT_DOT 32     /* internal to "git add -u/-A" */
  extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags);
  extern int add_file_to_index(struct index_state *, const char *path, int flags);
 -extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);
 +extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, unsigned int refresh_options);
  extern int ce_same_name(const struct cache_entry *a, const struct cache_entry *b);
+ extern void set_object_name_for_intent_to_add_entry(struct cache_entry *ce);
  extern int index_name_is_other(const struct index_state *, const char *, int);
  extern void *read_blob_data_from_index(struct index_state *, const char *, unsigned long *);
  
  #define CE_MATCH_RACY_IS_DIRTY                02
  /* do stat comparison even if CE_SKIP_WORKTREE is true */
  #define CE_MATCH_IGNORE_SKIP_WORKTREE 04
 +/* ignore non-existent files during stat update  */
 +#define CE_MATCH_IGNORE_MISSING               0x08
 +/* enable stat refresh */
 +#define CE_MATCH_REFRESH              0x10
  extern int ie_match_stat(const struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
  extern int ie_modified(const struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
  
 -extern int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec);
 -
  #define HASH_WRITE_OBJECT 1
  #define HASH_FORMAT_CHECK 2
  extern int index_fd(unsigned char *sha1, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
diff --combined read-cache.c
index 29c1047eeb7ce69d6a196ec80c23f66472142273,f0b1eaddabac8f5a4ceec166db49a6993cfe263e..6d8ee3a792d09aa347da275770aa775e6cd9eb33
@@@ -15,8 -15,7 +15,8 @@@
  #include "strbuf.h"
  #include "varint.h"
  
 -static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
 +static struct cache_entry *refresh_cache_entry(struct cache_entry *ce,
 +                                             unsigned int options);
  
  /* Mask for the name length in ce_flags in the on-disk index */
  
@@@ -48,7 -47,6 +48,7 @@@ static void replace_index_entry(struct 
        struct cache_entry *old = istate->cache[nr];
  
        remove_name_hash(istate, old);
 +      free(old);
        set_index_entry(istate, nr, ce);
        istate->cache_changed = 1;
  }
@@@ -60,7 -58,7 +60,7 @@@ void rename_index_entry_at(struct index
  
        new = xmalloc(cache_entry_size(namelen));
        copy_cache_entry(new, old);
 -      new->ce_flags &= ~CE_STATE_MASK;
 +      new->ce_flags &= ~CE_HASHED;
        new->ce_namelen = namelen;
        memcpy(new->name, new_name, namelen + 1);
  
@@@ -480,7 -478,6 +480,7 @@@ int remove_index_entry_at(struct index_
  
        record_resolve_undo(istate, ce);
        remove_name_hash(istate, ce);
 +      free(ce);
        istate->cache_changed = 1;
        istate->cache_nr--;
        if (pos >= istate->cache_nr)
@@@ -502,10 -499,8 +502,10 @@@ void remove_marked_cache_entries(struc
        unsigned int i, j;
  
        for (i = j = 0; i < istate->cache_nr; i++) {
 -              if (ce_array[i]->ce_flags & CE_REMOVE)
 +              if (ce_array[i]->ce_flags & CE_REMOVE) {
                        remove_name_hash(istate, ce_array[i]);
 +                      free(ce_array[i]);
 +              }
                else
                        ce_array[j++] = ce_array[i];
        }
@@@ -584,7 -579,7 +584,7 @@@ static struct cache_entry *create_alias
        return new;
  }
  
static void record_intent_to_add(struct cache_entry *ce)
void set_object_name_for_intent_to_add_entry(struct cache_entry *ce)
  {
        unsigned char sha1[20];
        if (write_sha1_file("", 0, blob_type, sha1))
@@@ -670,7 -665,7 +670,7 @@@ int add_to_index(struct index_state *is
                if (index_path(ce->sha1, path, st, HASH_WRITE_OBJECT))
                        return error("unable to index file %s", path);
        } else
-               record_intent_to_add(ce);
+               set_object_name_for_intent_to_add_entry(ce);
  
        if (ignore_case && alias && different_name(ce, alias))
                ce = create_alias_ce(ce, alias);
@@@ -701,7 -696,7 +701,7 @@@ int add_file_to_index(struct index_stat
  
  struct cache_entry *make_cache_entry(unsigned int mode,
                const unsigned char *sha1, const char *path, int stage,
 -              int refresh)
 +              unsigned int refresh_options)
  {
        int size, len;
        struct cache_entry *ce;
        ce->ce_namelen = len;
        ce->ce_mode = create_ce_mode(mode);
  
 -      if (refresh)
 -              return refresh_cache_entry(ce, 0);
 -
 -      return ce;
 +      return refresh_cache_entry(ce, refresh_options);
  }
  
  int ce_same_name(const struct cache_entry *a, const struct cache_entry *b)
        return ce_namelen(b) == len && !memcmp(a->name, b->name, len);
  }
  
 -int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec)
 -{
 -      return match_pathspec_depth(pathspec, ce->name, ce_namelen(ce), 0, NULL);
 -}
 -
  /*
   * We fundamentally don't like some paths: we don't want
   * dot or dot-dot anywhere, and for obvious reasons don't
@@@ -1026,12 -1029,10 +1026,12 @@@ static struct cache_entry *refresh_cach
        struct stat st;
        struct cache_entry *updated;
        int changed, size;
 +      int refresh = options & CE_MATCH_REFRESH;
        int ignore_valid = options & CE_MATCH_IGNORE_VALID;
        int ignore_skip_worktree = options & CE_MATCH_IGNORE_SKIP_WORKTREE;
 +      int ignore_missing = options & CE_MATCH_IGNORE_MISSING;
  
 -      if (ce_uptodate(ce))
 +      if (!refresh || ce_uptodate(ce))
                return ce;
  
        /*
        }
  
        if (lstat(ce->name, &st) < 0) {
 +              if (ignore_missing && errno == ENOENT)
 +                      return ce;
                if (err)
                        *err = errno;
                return NULL;
@@@ -1128,9 -1127,7 +1128,9 @@@ int refresh_index(struct index_state *i
        int ignore_submodules = (flags & REFRESH_IGNORE_SUBMODULES) != 0;
        int first = 1;
        int in_porcelain = (flags & REFRESH_IN_PORCELAIN);
 -      unsigned int options = really ? CE_MATCH_IGNORE_VALID : 0;
 +      unsigned int options = (CE_MATCH_REFRESH |
 +                              (really ? CE_MATCH_IGNORE_VALID : 0) |
 +                              (not_new ? CE_MATCH_IGNORE_MISSING : 0));
        const char *modified_fmt;
        const char *deleted_fmt;
        const char *typechange_fmt;
                if (ignore_submodules && S_ISGITLINK(ce->ce_mode))
                        continue;
  
 -              if (pathspec &&
 -                  !match_pathspec_depth(pathspec, ce->name, ce_namelen(ce), 0, seen))
 +              if (pathspec && !ce_path_match(ce, pathspec, seen))
                        filtered = 1;
  
                if (ce_stage(ce)) {
                if (!new) {
                        const char *fmt;
  
 -                      if (not_new && cache_errno == ENOENT)
 -                              continue;
                        if (really && cache_errno == EINVAL) {
                                /* If we are doing --really-refresh that
                                 * means the index is not valid anymore.
        return has_errors;
  }
  
 -static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really)
 +static struct cache_entry *refresh_cache_entry(struct cache_entry *ce,
 +                                             unsigned int options)
  {
 -      return refresh_cache_ent(&the_index, ce, really, NULL, NULL);
 +      return refresh_cache_ent(&the_index, ce, options, NULL, NULL);
  }
  
  
@@@ -1895,7 -1894,7 +1895,7 @@@ int read_index_unmerged(struct index_st
                new_ce->ce_mode = ce->ce_mode;
                if (add_index_entry(istate, new_ce, 0))
                        return error("%s: cannot drop to stage #0",
 -                                   ce->name);
 +                                   new_ce->name);
                i = index_name_pos(istate, new_ce->name, len);
        }
        return unmerged;