Skip to content

Commit f9e6c64

Browse files
pcloudsgitster
authored andcommitted
untracked cache: load from UNTR index extension
Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 83c094a commit f9e6c64

File tree

3 files changed

+226
-0
lines changed

3 files changed

+226
-0
lines changed

dir.c

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2283,3 +2283,222 @@ void write_untracked_extension(struct strbuf *out, struct untracked_cache *untra
22832283
strbuf_release(&wd.sb_stat);
22842284
strbuf_release(&wd.sb_sha1);
22852285
}
2286+
2287+
static void free_untracked(struct untracked_cache_dir *ucd)
2288+
{
2289+
int i;
2290+
if (!ucd)
2291+
return;
2292+
for (i = 0; i < ucd->dirs_nr; i++)
2293+
free_untracked(ucd->dirs[i]);
2294+
for (i = 0; i < ucd->untracked_nr; i++)
2295+
free(ucd->untracked[i]);
2296+
free(ucd->untracked);
2297+
free(ucd->dirs);
2298+
free(ucd);
2299+
}
2300+
2301+
void free_untracked_cache(struct untracked_cache *uc)
2302+
{
2303+
if (uc)
2304+
free_untracked(uc->root);
2305+
free(uc);
2306+
}
2307+
2308+
struct read_data {
2309+
int index;
2310+
struct untracked_cache_dir **ucd;
2311+
struct ewah_bitmap *check_only;
2312+
struct ewah_bitmap *valid;
2313+
struct ewah_bitmap *sha1_valid;
2314+
const unsigned char *data;
2315+
const unsigned char *end;
2316+
};
2317+
2318+
static void stat_data_from_disk(struct stat_data *to, const struct stat_data *from)
2319+
{
2320+
to->sd_ctime.sec = get_be32(&from->sd_ctime.sec);
2321+
to->sd_ctime.nsec = get_be32(&from->sd_ctime.nsec);
2322+
to->sd_mtime.sec = get_be32(&from->sd_mtime.sec);
2323+
to->sd_mtime.nsec = get_be32(&from->sd_mtime.nsec);
2324+
to->sd_dev = get_be32(&from->sd_dev);
2325+
to->sd_ino = get_be32(&from->sd_ino);
2326+
to->sd_uid = get_be32(&from->sd_uid);
2327+
to->sd_gid = get_be32(&from->sd_gid);
2328+
to->sd_size = get_be32(&from->sd_size);
2329+
}
2330+
2331+
static int read_one_dir(struct untracked_cache_dir **untracked_,
2332+
struct read_data *rd)
2333+
{
2334+
struct untracked_cache_dir ud, *untracked;
2335+
const unsigned char *next, *data = rd->data, *end = rd->end;
2336+
unsigned int value;
2337+
int i, len;
2338+
2339+
memset(&ud, 0, sizeof(ud));
2340+
2341+
next = data;
2342+
value = decode_varint(&next);
2343+
if (next > end)
2344+
return -1;
2345+
ud.recurse = 1;
2346+
ud.untracked_alloc = value;
2347+
ud.untracked_nr = value;
2348+
if (ud.untracked_nr)
2349+
ud.untracked = xmalloc(sizeof(*ud.untracked) * ud.untracked_nr);
2350+
data = next;
2351+
2352+
next = data;
2353+
ud.dirs_alloc = ud.dirs_nr = decode_varint(&next);
2354+
if (next > end)
2355+
return -1;
2356+
ud.dirs = xmalloc(sizeof(*ud.dirs) * ud.dirs_nr);
2357+
data = next;
2358+
2359+
len = strlen((const char *)data);
2360+
next = data + len + 1;
2361+
if (next > rd->end)
2362+
return -1;
2363+
*untracked_ = untracked = xmalloc(sizeof(*untracked) + len);
2364+
memcpy(untracked, &ud, sizeof(ud));
2365+
memcpy(untracked->name, data, len + 1);
2366+
data = next;
2367+
2368+
for (i = 0; i < untracked->untracked_nr; i++) {
2369+
len = strlen((const char *)data);
2370+
next = data + len + 1;
2371+
if (next > rd->end)
2372+
return -1;
2373+
untracked->untracked[i] = xstrdup((const char*)data);
2374+
data = next;
2375+
}
2376+
2377+
rd->ucd[rd->index++] = untracked;
2378+
rd->data = data;
2379+
2380+
for (i = 0; i < untracked->dirs_nr; i++) {
2381+
len = read_one_dir(untracked->dirs + i, rd);
2382+
if (len < 0)
2383+
return -1;
2384+
}
2385+
return 0;
2386+
}
2387+
2388+
static void set_check_only(size_t pos, void *cb)
2389+
{
2390+
struct read_data *rd = cb;
2391+
struct untracked_cache_dir *ud = rd->ucd[pos];
2392+
ud->check_only = 1;
2393+
}
2394+
2395+
static void read_stat(size_t pos, void *cb)
2396+
{
2397+
struct read_data *rd = cb;
2398+
struct untracked_cache_dir *ud = rd->ucd[pos];
2399+
if (rd->data + sizeof(struct stat_data) > rd->end) {
2400+
rd->data = rd->end + 1;
2401+
return;
2402+
}
2403+
stat_data_from_disk(&ud->stat_data, (struct stat_data *)rd->data);
2404+
rd->data += sizeof(struct stat_data);
2405+
ud->valid = 1;
2406+
}
2407+
2408+
static void read_sha1(size_t pos, void *cb)
2409+
{
2410+
struct read_data *rd = cb;
2411+
struct untracked_cache_dir *ud = rd->ucd[pos];
2412+
if (rd->data + 20 > rd->end) {
2413+
rd->data = rd->end + 1;
2414+
return;
2415+
}
2416+
hashcpy(ud->exclude_sha1, rd->data);
2417+
rd->data += 20;
2418+
}
2419+
2420+
static void load_sha1_stat(struct sha1_stat *sha1_stat,
2421+
const struct stat_data *stat,
2422+
const unsigned char *sha1)
2423+
{
2424+
stat_data_from_disk(&sha1_stat->stat, stat);
2425+
hashcpy(sha1_stat->sha1, sha1);
2426+
sha1_stat->valid = 1;
2427+
}
2428+
2429+
struct untracked_cache *read_untracked_extension(const void *data, unsigned long sz)
2430+
{
2431+
const struct ondisk_untracked_cache *ouc;
2432+
struct untracked_cache *uc;
2433+
struct read_data rd;
2434+
const unsigned char *next = data, *end = (const unsigned char *)data + sz;
2435+
int len;
2436+
2437+
if (sz <= 1 || end[-1] != '\0')
2438+
return NULL;
2439+
end--;
2440+
2441+
ouc = (const struct ondisk_untracked_cache *)next;
2442+
if (next + ouc_size(0) > end)
2443+
return NULL;
2444+
2445+
uc = xcalloc(1, sizeof(*uc));
2446+
load_sha1_stat(&uc->ss_info_exclude, &ouc->info_exclude_stat,
2447+
ouc->info_exclude_sha1);
2448+
load_sha1_stat(&uc->ss_excludes_file, &ouc->excludes_file_stat,
2449+
ouc->excludes_file_sha1);
2450+
uc->dir_flags = get_be32(&ouc->dir_flags);
2451+
uc->exclude_per_dir = xstrdup(ouc->exclude_per_dir);
2452+
/* NUL after exclude_per_dir is covered by sizeof(*ouc) */
2453+
next += ouc_size(strlen(ouc->exclude_per_dir));
2454+
if (next >= end)
2455+
goto done2;
2456+
2457+
len = decode_varint(&next);
2458+
if (next > end || len == 0)
2459+
goto done2;
2460+
2461+
rd.valid = ewah_new();
2462+
rd.check_only = ewah_new();
2463+
rd.sha1_valid = ewah_new();
2464+
rd.data = next;
2465+
rd.end = end;
2466+
rd.index = 0;
2467+
rd.ucd = xmalloc(sizeof(*rd.ucd) * len);
2468+
2469+
if (read_one_dir(&uc->root, &rd) || rd.index != len)
2470+
goto done;
2471+
2472+
next = rd.data;
2473+
len = ewah_read_mmap(rd.valid, next, end - next);
2474+
if (len < 0)
2475+
goto done;
2476+
2477+
next += len;
2478+
len = ewah_read_mmap(rd.check_only, next, end - next);
2479+
if (len < 0)
2480+
goto done;
2481+
2482+
next += len;
2483+
len = ewah_read_mmap(rd.sha1_valid, next, end - next);
2484+
if (len < 0)
2485+
goto done;
2486+
2487+
ewah_each_bit(rd.check_only, set_check_only, &rd);
2488+
rd.data = next + len;
2489+
ewah_each_bit(rd.valid, read_stat, &rd);
2490+
ewah_each_bit(rd.sha1_valid, read_sha1, &rd);
2491+
next = rd.data;
2492+
2493+
done:
2494+
free(rd.ucd);
2495+
ewah_free(rd.valid);
2496+
ewah_free(rd.check_only);
2497+
ewah_free(rd.sha1_valid);
2498+
done2:
2499+
if (next != end) {
2500+
free_untracked_cache(uc);
2501+
uc = NULL;
2502+
}
2503+
return uc;
2504+
}

dir.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,5 +298,7 @@ static inline int dir_path_match(const struct dir_entry *ent,
298298
has_trailing_dir);
299299
}
300300

301+
void free_untracked_cache(struct untracked_cache *);
302+
struct untracked_cache *read_untracked_extension(const void *data, unsigned long sz);
301303
void write_untracked_extension(struct strbuf *out, struct untracked_cache *untracked);
302304
#endif

read-cache.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,6 +1371,9 @@ static int read_index_extension(struct index_state *istate,
13711371
if (read_link_extension(istate, data, sz))
13721372
return -1;
13731373
break;
1374+
case CACHE_EXT_UNTRACKED:
1375+
istate->untracked = read_untracked_extension(data, sz);
1376+
break;
13741377
default:
13751378
if (*ext < 'A' || 'Z' < *ext)
13761379
return error("index uses %.4s extension, which we do not understand",
@@ -1662,6 +1665,8 @@ int discard_index(struct index_state *istate)
16621665
istate->cache = NULL;
16631666
istate->cache_alloc = 0;
16641667
discard_split_index(istate);
1668+
free_untracked_cache(istate->untracked);
1669+
istate->untracked = NULL;
16651670
return 0;
16661671
}
16671672

0 commit comments

Comments
 (0)