untracked cache: load from UNTR index extension
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Nguyễn Thái Ngọc Duy committed
Mar 8, 2015 at 17:12 UTC
f9e6c649589e0940ccb82821107fb658277ed86b
3 files changed
+226
dir.c
+219
@@ -2283,3 +2283,222 @@ void write_untracked_extension(struct strbuf *out, struct untracked_cache *untra
2283
strbuf_release(&wd.sb_stat);
2284
strbuf_release(&wd.sb_sha1);
2285
}
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
+2
@@ -298,5 +298,7 @@ static inline int dir_path_match(const struct dir_entry *ent,
298
has_trailing_dir);
299
}
300
301
+void free_untracked_cache(struct untracked_cache *);
302
+struct untracked_cache *read_untracked_extension(const void *data, unsigned long sz);
303
void write_untracked_extension(struct strbuf *out, struct untracked_cache *untracked);
304
#endif
read-cache.c
+5
@@ -1371,6 +1371,9 @@ static int read_index_extension(struct index_state *istate,
1371
if (read_link_extension(istate, data, sz))
1372
return -1;
1373
break;
1374
+ case CACHE_EXT_UNTRACKED:
1375
+ istate->untracked = read_untracked_extension(data, sz);
1376
+ break;
1377
default:
1378
if (*ext < 'A' || 'Z' < *ext)
1379
return error("index uses %.4s extension, which we do not understand",
@@ -1662,6 +1665,8 @@ int discard_index(struct index_state *istate)
1665
istate->cache = NULL;
1666
istate->cache_alloc = 0;
1667
discard_split_index(istate);
1668
+ free_untracked_cache(istate->untracked);
1669
+ istate->untracked = NULL;
1670
return 0;
1671
}
1672