Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 cache.h      |  3 +++
 dir.c        | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 dir.h        |  1 +
 read-cache.c | 12 +++++++++
 4 files changed, 101 insertions(+)

diff --git a/cache.h b/cache.h
index 5b86065..4f903fa 100644
--- a/cache.h
+++ b/cache.h
@@ -298,6 +298,8 @@ static inline unsigned int canon_mode(unsigned int mode)
 #define SPLIT_INDEX_ORDERED    (1 << 6)
 
 struct split_index;
+struct untracked_cache;
+
 struct index_state {
        struct cache_entry **cache;
        unsigned int version;
@@ -311,6 +313,7 @@ struct index_state {
        struct hashmap name_hash;
        struct hashmap dir_hash;
        unsigned char sha1[20];
+       struct untracked_cache *untracked;
 };
 
 extern struct index_state the_index;
diff --git a/dir.c b/dir.c
index d4f9830..d696388 100644
--- a/dir.c
+++ b/dir.c
@@ -12,6 +12,7 @@
 #include "refs.h"
 #include "wildmatch.h"
 #include "pathspec.h"
+#include "varint.h"
 
 struct path_simplify {
        int len;
@@ -2145,3 +2146,87 @@ void clear_directory(struct dir_struct *dir)
        }
        strbuf_release(&dir->basebuf);
 }
+
+struct ondisk_untracked_cache {
+       struct stat_data info_exclude_stat;
+       struct stat_data excludes_file_stat;
+       uint32_t dir_flags;
+       unsigned char info_exclude_sha1[20];
+       unsigned char excludes_file_sha1[20];
+       char exclude_per_dir[1];
+};
+
+static void stat_data_to_disk(struct stat_data *to, const struct stat_data 
*from)
+{
+       to->sd_ctime.sec  = htonl(from->sd_ctime.sec);
+       to->sd_ctime.nsec = htonl(from->sd_ctime.nsec);
+       to->sd_mtime.sec  = htonl(from->sd_mtime.sec);
+       to->sd_mtime.nsec = htonl(from->sd_mtime.nsec);
+       to->sd_dev        = htonl(from->sd_dev);
+       to->sd_ino        = htonl(from->sd_ino);
+       to->sd_uid        = htonl(from->sd_uid);
+       to->sd_gid        = htonl(from->sd_gid);
+       to->sd_size       = htonl(from->sd_size);
+}
+
+static void write_one_dir(struct strbuf *out, struct untracked_cache_dir 
*untracked)
+{
+       struct stat_data stat_data;
+       unsigned char intbuf[16];
+       unsigned int intlen, value;
+       int i;
+
+       stat_data_to_disk(&stat_data, &untracked->stat_data);
+       strbuf_add(out, &stat_data, sizeof(stat_data));
+       strbuf_add(out, untracked->exclude_sha1, 20);
+
+       /*
+        * untracked_nr should be reset whenever valid is clear, but
+        * for safety..
+        */
+       if (!untracked->valid) {
+               untracked->untracked_nr = 0;
+               untracked->check_only = 0;
+       }
+
+       value  = untracked->valid;
+       value |= untracked->check_only   << 1;
+       value |= untracked->untracked_nr << 2;
+       intlen = encode_varint(value, intbuf);
+       strbuf_add(out, intbuf, intlen);
+
+       /* skip non-recurse directories */
+       for (i = 0, value = 0; i < untracked->dirs_nr; i++)
+               if (untracked->dirs[i]->recurse)
+                       value++;
+       intlen = encode_varint(value, intbuf);
+       strbuf_add(out, intbuf, intlen);
+
+       strbuf_add(out, untracked->name, strlen(untracked->name) + 1);
+
+       for (i = 0; i < untracked->untracked_nr; i++)
+               strbuf_add(out, untracked->untracked[i],
+                          strlen(untracked->untracked[i]) + 1);
+
+       for (i = 0; i < untracked->dirs_nr; i++)
+               if (untracked->dirs[i]->recurse)
+                       write_one_dir(out, untracked->dirs[i]);
+}
+
+void write_untracked_extension(struct strbuf *out, struct untracked_cache 
*untracked)
+{
+       struct ondisk_untracked_cache *ouc;
+       int len = 0;
+       if (untracked->exclude_per_dir)
+               len = strlen(untracked->exclude_per_dir);
+       ouc = xmalloc(sizeof(*ouc) + len);
+       stat_data_to_disk(&ouc->info_exclude_stat, 
&untracked->ss_info_exclude.stat);
+       stat_data_to_disk(&ouc->excludes_file_stat, 
&untracked->ss_excludes_file.stat);
+       hashcpy(ouc->info_exclude_sha1, untracked->ss_info_exclude.sha1);
+       hashcpy(ouc->excludes_file_sha1, untracked->ss_excludes_file.sha1);
+       ouc->dir_flags = htonl(untracked->dir_flags);
+       memcpy(ouc->exclude_per_dir, untracked->exclude_per_dir, len + 1);
+       strbuf_add(out, ouc, sizeof(*ouc) + len);
+       if (untracked->root)
+               write_one_dir(out, untracked->root);
+}
diff --git a/dir.h b/dir.h
index c302dcb..7ef0f63 100644
--- a/dir.h
+++ b/dir.h
@@ -297,4 +297,5 @@ static inline int dir_path_match(const struct dir_entry 
*ent,
                              has_trailing_dir);
 }
 
+void write_untracked_extension(struct strbuf *out, struct untracked_cache 
*untracked);
 #endif
diff --git a/read-cache.c b/read-cache.c
index 8f3e9eb..efff4e2 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -38,6 +38,7 @@ static struct cache_entry *refresh_cache_entry(struct 
cache_entry *ce,
 #define CACHE_EXT_TREE 0x54524545      /* "TREE" */
 #define CACHE_EXT_RESOLVE_UNDO 0x52455543 /* "REUC" */
 #define CACHE_EXT_LINK 0x6c696e6b        /* "link" */
+#define CACHE_EXT_UNTRACKED 0x554E5452   /* "UNTR" */
 
 /* changes that can be kept in $GIT_DIR/index (basically all extensions) */
 #define EXTMASK (RESOLVE_UNDO_CHANGED | CACHE_TREE_CHANGED | \
@@ -2035,6 +2036,17 @@ static int do_write_index(struct index_state *istate, 
int newfd,
                if (err)
                        return -1;
        }
+       if (istate->untracked) {
+               struct strbuf sb = STRBUF_INIT;
+
+               write_untracked_extension(&sb, istate->untracked);
+               err = write_index_ext_header(&c, newfd, CACHE_EXT_UNTRACKED,
+                                            sb.len) < 0 ||
+                       ce_write(&c, newfd, sb.buf, sb.len) < 0;
+               strbuf_release(&sb);
+               if (err)
+                       return -1;
+       }
 
        if (ce_flush(&c, newfd, istate->sha1) || fstat(newfd, &st))
                return -1;
-- 
2.1.0.rc0.78.gc0d8480

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to