Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]>
---
dir.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
dir.h | 2 +
read-cache.c | 5 +++
3 files changed, 142 insertions(+)
diff --git a/dir.c b/dir.c
index 4e15f20..bc196b3 100644
--- a/dir.c
+++ b/dir.c
@@ -2223,3 +2223,138 @@ void write_untracked_extension(struct strbuf *out,
struct untracked_cache *untra
if (untracked->root)
write_one_dir(out, untracked->root);
}
+
+static void free_untracked(struct untracked_cache_dir *ucd)
+{
+ int i;
+ if (!ucd)
+ return;
+ for (i = 0; i < ucd->dirs_nr; i++)
+ free_untracked(ucd->dirs[i]);
+ for (i = 0; i < ucd->untracked_nr; i++)
+ free(ucd->untracked[i]);
+ free(ucd->untracked);
+ free(ucd->dirs);
+ free(ucd);
+}
+
+void free_untracked_cache(struct untracked_cache *uc)
+{
+ if (uc)
+ free_untracked(uc->root);
+ free(uc);
+}
+
+static void stat_data_from_disk(struct stat_data *to, const struct stat_data
*from)
+{
+ to->sd_ctime.sec = get_be32(&from->sd_ctime.sec);
+ to->sd_ctime.nsec = get_be32(&from->sd_ctime.nsec);
+ to->sd_mtime.sec = get_be32(&from->sd_mtime.sec);
+ to->sd_mtime.nsec = get_be32(&from->sd_mtime.nsec);
+ to->sd_dev = get_be32(&from->sd_dev);
+ to->sd_ino = get_be32(&from->sd_ino);
+ to->sd_uid = get_be32(&from->sd_uid);
+ to->sd_gid = get_be32(&from->sd_gid);
+ to->sd_size = get_be32(&from->sd_size);
+}
+
+static int read_one_dir(struct untracked_cache_dir **untracked_,
+ const unsigned char *data_, unsigned long sz)
+{
+#define NEXT(x) \
+ next = data + (x); \
+ if (next > data_ + sz) \
+ return -1;
+
+ struct untracked_cache_dir ud, *untracked;
+ const unsigned char *next, *data = data_;
+ unsigned int value;
+ int i, len;
+
+ memset(&ud, 0, sizeof(ud));
+
+ NEXT(sizeof(struct stat_data));
+ stat_data_from_disk(&ud.stat_data, (struct stat_data *)data);
+ data = next;
+
+ NEXT(20);
+ hashcpy(ud.exclude_sha1, data);
+ data = next;
+
+ next = data;
+ value = decode_varint(&next);
+ if (next > data_ + sz)
+ return -1;
+ ud.recurse = 1;
+ ud.valid = value & 1;
+ ud.check_only = (value >> 1) & 1;
+ ud.untracked_alloc = ud.untracked_nr = value >> 2;
+ if (ud.untracked_nr)
+ ud.untracked = xmalloc(sizeof(*ud.untracked) * ud.untracked_nr);
+ data = next;
+
+ next = data;
+ ud.dirs_alloc = ud.dirs_nr = decode_varint(&next);
+ if (next > data_ + sz)
+ return -1;
+ ud.dirs = xmalloc(sizeof(*ud.dirs) * ud.dirs_nr);
+ data = next;
+
+ len = strlen((const char *)data);
+ NEXT(len + 1);
+ *untracked_ = untracked = xmalloc(sizeof(*untracked) + len);
+ memcpy(untracked, &ud, sizeof(ud));
+ memcpy(untracked->name, data, len + 1);
+ data = next;
+
+ for (i = 0; i < untracked->untracked_nr; i++) {
+ len = strlen((const char *)data);
+ NEXT(len + 1);
+ untracked->untracked[i] = xstrdup((const char*)data);
+ data = next;
+ }
+
+ for (i = 0; i < untracked->dirs_nr; i++) {
+ len = read_one_dir(untracked->dirs + i, data, sz - (data -
data_));
+ if (len < 0)
+ return -1;
+ data += len;
+ }
+ return data - data_;
+}
+
+static void load_sha1_stat(struct sha1_stat *sha1_stat,
+ const struct stat_data *stat,
+ const unsigned char *sha1)
+{
+ stat_data_from_disk(&sha1_stat->stat, stat);
+ hashcpy(sha1_stat->sha1, sha1);
+ sha1_stat->valid = 1;
+}
+
+struct untracked_cache *read_untracked_extension(const void *data, unsigned
long sz)
+{
+ const struct ondisk_untracked_cache *ouc = data;
+ struct untracked_cache *uc;
+ int len;
+
+ if (sz < sizeof(*ouc))
+ return NULL;
+
+ uc = xcalloc(1, sizeof(*uc));
+ load_sha1_stat(&uc->ss_info_exclude, &ouc->info_exclude_stat,
+ ouc->info_exclude_sha1);
+ load_sha1_stat(&uc->ss_excludes_file, &ouc->excludes_file_stat,
+ ouc->excludes_file_sha1);
+ uc->dir_flags = get_be32(&ouc->dir_flags);
+ uc->exclude_per_dir = xstrdup(ouc->exclude_per_dir);
+ len = sizeof(*ouc) + strlen(ouc->exclude_per_dir);
+ if (sz == len)
+ return uc;
+ if (sz > len &&
+ read_one_dir(&uc->root, (const unsigned char *)data + len,
+ sz - len) == sz - len)
+ return uc;
+ free_untracked_cache(uc);
+ return NULL;
+}
diff --git a/dir.h b/dir.h
index c771057..14ee4fd 100644
--- a/dir.h
+++ b/dir.h
@@ -298,5 +298,7 @@ static inline int dir_path_match(const struct dir_entry
*ent,
has_trailing_dir);
}
+void free_untracked_cache(struct untracked_cache *);
+struct untracked_cache *read_untracked_extension(const void *data, unsigned
long sz);
void write_untracked_extension(struct strbuf *out, struct untracked_cache
*untracked);
#endif
diff --git a/read-cache.c b/read-cache.c
index 26e938d..f5bd174 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -1366,6 +1366,9 @@ static int read_index_extension(struct index_state
*istate,
if (read_link_extension(istate, data, sz))
return -1;
break;
+ case CACHE_EXT_UNTRACKED:
+ istate->untracked = read_untracked_extension(data, sz);
+ break;
default:
if (*ext < 'A' || 'Z' < *ext)
return error("index uses %.4s extension, which we do
not understand",
@@ -1631,6 +1634,8 @@ int discard_index(struct index_state *istate)
istate->cache = NULL;
istate->cache_alloc = 0;
discard_split_index(istate);
+ free_untracked_cache(istate->untracked);
+ istate->untracked = NULL;
return 0;
}
--
2.1.0.rc0.78.gc0d8480
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html