FIXME: save check_only --- cache.h | 3 ++ dir.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ dir.h | 1 + read-cache.c | 12 ++++++++ 4 files changed, 107 insertions(+) diff --git a/cache.h b/cache.h index 107ac61..06fcb6b 100644 --- a/cache.h +++ b/cache.h @@ -268,6 +268,8 @@ static inline unsigned int canon_mode(unsigned int mode) #define cache_entry_size(len) (offsetof(struct cache_entry,name) + (len) + 1) + +struct untracked_cache; struct index_state { struct cache_entry **cache; unsigned int version; @@ -279,6 +281,7 @@ struct index_state { initialized : 1; struct hashmap name_hash; struct hashmap dir_hash; + struct untracked_cache *untracked; }; extern struct index_state the_index; diff --git a/dir.c b/dir.c index b5bfda8..b7d394a 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; @@ -2165,3 +2166,93 @@ 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; + } + + /* + * encode_varint does not deal with signed integers. Use the + * lowest bit to store the sign. + */ + value = untracked->untracked_nr << 2; + if (untracked->valid) + value |= 1; + if (untracked->check_only) + value |= 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->info_exclude_stat); + stat_data_to_disk(&ouc->excludes_file_stat, &untracked->excludes_file_stat); + hashcpy(ouc->info_exclude_sha1, untracked->info_exclude_sha1); + hashcpy(ouc->excludes_file_sha1, untracked->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 5dde37b..e520d58 100644 --- a/dir.h +++ b/dir.h @@ -295,4 +295,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 ba13353..a619666 100644 --- a/read-cache.c +++ b/read-cache.c @@ -34,6 +34,7 @@ static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, #define CACHE_EXT(s) ( (s[0]<<24)|(s[1]<<16)|(s[2]<<8)|(s[3]) ) #define CACHE_EXT_TREE 0x54524545 /* "TREE" */ #define CACHE_EXT_RESOLVE_UNDO 0x52455543 /* "REUC" */ +#define CACHE_EXT_UNTRACKED 0x554E5452 /* "UNTR" */ struct index_state the_index; @@ -1869,6 +1870,17 @@ int 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) || fstat(newfd, &st)) return -1; -- 1.9.1.346.ga2b5940 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html