32
};
33
34
static enum path_treatment read_directory_recursive(struct dir_struct *dir,
35
- const char *path, int len,
35
+ const char *path, int len, struct untracked_cache_dir *untracked,
36
int check_only, const struct path_simplify *simplify);
37
static int get_dtype(struct dirent *de, const char *path, int len);
38
534
*last_space = '\0';
535
}
536
537
+/*
538
+ * Given a subdirectory name and "dir" of the current directory,
539
+ * search the subdir in "dir" and return it, or create a new one if it
540
+ * does not exist in "dir".
541
+ *
542
+ * If "name" has the trailing slash, it'll be excluded in the search.
543
+ */
544
+static struct untracked_cache_dir *lookup_untracked(struct untracked_cache *uc,
545
+ struct untracked_cache_dir *dir,
546
+ const char *name, int len)
547
+{
548
+ int first, last;
549
+ struct untracked_cache_dir *d;
550
+ if (!dir)
551
+ return NULL;
552
+ if (len && name[len - 1] == '/')
553
+ len--;
554
+ first = 0;
555
+ last = dir->dirs_nr;
556
+ while (last > first) {
557
+ int cmp, next = (last + first) >> 1;
558
+ d = dir->dirs[next];
559
+ cmp = strncmp(name, d->name, len);
560
+ if (!cmp && strlen(d->name) > len)
561
+ cmp = -1;
562
+ if (!cmp)
563
+ return d;
564
+ if (cmp < 0) {
565
+ last = next;
566
+ continue;
567
+ }
568
+ first = next+1;
569
+ }
570
+
571
+ uc->dir_created++;
572
+ d = xmalloc(sizeof(*d) + len + 1);
573
+ memset(d, 0, sizeof(*d));
574
+ memcpy(d->name, name, len);
575
+ d->name[len] = '\0';
576
+
577
+ ALLOC_GROW(dir->dirs, dir->dirs_nr + 1, dir->dirs_alloc);
578
+ memmove(dir->dirs + first + 1, dir->dirs + first,
579
+ (dir->dirs_nr - first) * sizeof(*dir->dirs));
580
+ dir->dirs_nr++;
581
+ dir->dirs[first] = d;
582
+ return d;
583
+}
584
+
585
/*
586
* Given a file with name "fname", read it (either from disk, or from
587
* the index if "check_index" is non-zero), parse it and store the
694
/*
695
* Used to set up core.excludesfile and .git/info/exclude lists.
696
*/
649
-void add_excludes_from_file(struct dir_struct *dir, const char *fname)
697
+static void add_excludes_from_file_1(struct dir_struct *dir, const char *fname,
698
+ struct sha1_stat *sha1_stat)
699
{
700
struct exclude_list *el;
701
el = add_exclude_list(dir, EXC_FILE, fname);
653
- if (add_excludes_from_file_to_list(fname, "", 0, el, 0) < 0)
702
+ if (add_excludes(fname, "", 0, el, 0, sha1_stat) < 0)
703
die("cannot use %s as an exclude file", fname);
704
}
705
706
+void add_excludes_from_file(struct dir_struct *dir, const char *fname)
707
+{
708
+ add_excludes_from_file_1(dir, fname, NULL);
709
+}
710
+
711
int match_basename(const char *basename, int basenamelen,
712
const char *pattern, int prefix, int patternlen,
713
int flags)
882
struct exclude_list_group *group;
883
struct exclude_list *el;
884
struct exclude_stack *stk = NULL;
885
+ struct untracked_cache_dir *untracked;
886
int current;
887
888
group = &dir->exclude_list_group[EXC_DIRS];
920
/* Read from the parent directories and push them down. */
921
current = stk ? stk->baselen : -1;
922
strbuf_setlen(&dir->basebuf, current < 0 ? 0 : current);
923
+ if (dir->untracked)
924
+ untracked = stk ? stk->ucd : dir->untracked->root;
925
+ else
926
+ untracked = NULL;
927
+
928
while (current < baselen) {
929
const char *cp;
930
+ struct sha1_stat sha1_stat;
931
932
stk = xcalloc(1, sizeof(*stk));
933
if (current < 0) {
938
if (!cp)
939
die("oops in prep_exclude");
940
cp++;
941
+ untracked =
942
+ lookup_untracked(dir->untracked, untracked,
943
+ base + current,
944
+ cp - base - current);
945
}
946
stk->prev = dir->exclude_stack;
947
stk->baselen = cp - base;
948
stk->exclude_ix = group->nr;
949
+ stk->ucd = untracked;
950
el = add_exclude_list(dir, EXC_DIRS, NULL);
951
strbuf_add(&dir->basebuf, base + current, stk->baselen - current);
952
assert(stk->baselen == dir->basebuf.len);
969
}
970
971
/* Try to read per-directory file */
972
+ hashclr(sha1_stat.sha1);
973
+ sha1_stat.valid = 0;
974
if (dir->exclude_per_dir) {
975
/*
976
* dir->basebuf gets reused by the traversal, but we
984
strbuf_addbuf(&sb, &dir->basebuf);
985
strbuf_addstr(&sb, dir->exclude_per_dir);
986
el->src = strbuf_detach(&sb, NULL);
919
- add_excludes_from_file_to_list(el->src, el->src,
920
- stk->baselen, el, 1);
987
+ add_excludes(el->src, el->src, stk->baselen, el, 1,
988
+ untracked ? &sha1_stat : NULL);
989
+ }
990
+ if (untracked) {
991
+ hashcpy(untracked->exclude_sha1, sha1_stat.sha1);
992
}
993
dir->exclude_stack = stk;
994
current = stk->baselen;
1169
* (c) otherwise, we recurse into it.
1170
*/
1171
static enum path_treatment treat_directory(struct dir_struct *dir,
1172
+ struct untracked_cache_dir *untracked,
1173
const char *dirname, int len, int exclude,
1174
const struct path_simplify *simplify)
1175
{
1197
if (!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
1198
return exclude ? path_excluded : path_untracked;
1199
1128
- return read_directory_recursive(dir, dirname, len, 1, simplify);
1200
+ untracked = lookup_untracked(dir->untracked, untracked, dirname, len);
1201
+ return read_directory_recursive(dir, dirname, len,
1202
+ untracked, 1, simplify);
1203
}
1204
1205
/*
1315
}
1316
1317
static enum path_treatment treat_one_path(struct dir_struct *dir,
1318
+ struct untracked_cache_dir *untracked,
1319
struct strbuf *path,
1320
const struct path_simplify *simplify,
1321
int dtype, struct dirent *de)
1368
return path_none;
1369
case DT_DIR:
1370
strbuf_addch(path, '/');
1296
- return treat_directory(dir, path->buf, path->len, exclude,
1371
+ return treat_directory(dir, untracked, path->buf, path->len, exclude,
1372
simplify);
1373
case DT_REG:
1374
case DT_LNK:
1377
}
1378
1379
static enum path_treatment treat_path(struct dir_struct *dir,
1380
+ struct untracked_cache_dir *untracked,
1381
struct dirent *de,
1382
struct strbuf *path,
1383
int baselen,
1393
return path_none;
1394
1395
dtype = DTYPE(de);
1320
- return treat_one_path(dir, path, simplify, dtype, de);
1396
+ return treat_one_path(dir, untracked, path, simplify, dtype, de);
1397
+}
1398
+
1399
+static void add_untracked(struct untracked_cache_dir *dir, const char *name)
1400
+{
1401
+ if (!dir)
1402
+ return;
1403
+ ALLOC_GROW(dir->untracked, dir->untracked_nr + 1,
1404
+ dir->untracked_alloc);
1405
+ dir->untracked[dir->untracked_nr++] = xstrdup(name);
1406
}
1407
1408
/*
1418
*/
1419
static enum path_treatment read_directory_recursive(struct dir_struct *dir,
1420
const char *base, int baselen,
1336
- int check_only,
1421
+ struct untracked_cache_dir *untracked, int check_only,
1422
const struct path_simplify *simplify)
1423
{
1424
DIR *fdir;
1432
if (!fdir)
1433
goto out;
1434
1435
+ if (untracked)
1436
+ untracked->check_only = !!check_only;
1437
+
1438
while ((de = readdir(fdir)) != NULL) {
1439
/* check how the file or directory should be treated */
1352
- state = treat_path(dir, de, &path, baselen, simplify);
1440
+ state = treat_path(dir, untracked, de, &path, baselen, simplify);
1441
+
1442
if (state > dir_state)
1443
dir_state = state;
1444
1445
/* recurse into subdir if instructed by treat_path */
1446
if (state == path_recurse) {
1358
- subdir_state = read_directory_recursive(dir, path.buf,
1359
- path.len, check_only, simplify);
1447
+ struct untracked_cache_dir *ud;
1448
+ ud = lookup_untracked(dir->untracked, untracked,
1449
+ path.buf + baselen,
1450
+ path.len - baselen);
1451
+ subdir_state =
1452
+ read_directory_recursive(dir, path.buf, path.len,
1453
+ ud, check_only, simplify);
1454
if (subdir_state > dir_state)
1455
dir_state = subdir_state;
1456
}
1457
1458
if (check_only) {
1459
/* abort early if maximum state has been reached */
1366
- if (dir_state == path_untracked)
1460
+ if (dir_state == path_untracked) {
1461
+ if (untracked)
1462
+ add_untracked(untracked, path.buf + baselen);
1463
break;
1464
+ }
1465
/* skip the dir_add_* part */
1466
continue;
1467
}
1479
break;
1480
1481
case path_untracked:
1385
- if (!(dir->flags & DIR_SHOW_IGNORED))
1386
- dir_add_name(dir, path.buf, path.len);
1482
+ if (dir->flags & DIR_SHOW_IGNORED)
1483
+ break;
1484
+ dir_add_name(dir, path.buf, path.len);
1485
+ if (untracked)
1486
+ add_untracked(untracked, path.buf + baselen);
1487
break;
1488
1489
default:
1560
break;
1561
if (simplify_away(sb.buf, sb.len, simplify))
1562
break;
1463
- if (treat_one_path(dir, &sb, simplify,
1563
+ if (treat_one_path(dir, NULL, &sb, simplify,
1564
DT_DIR, NULL) == path_none)
1565
break; /* do not recurse into it */
1566
if (len <= baselen) {
1600
*/
1601
simplify = create_simplify(pathspec ? pathspec->_raw : NULL);
1602
if (!len || treat_leading_path(dir, path, len, simplify))
1503
- read_directory_recursive(dir, path, len, 0, simplify);
1603
+ read_directory_recursive(dir, path, len,
1604
+ dir->untracked ? dir->untracked->root : NULL,
1605
+ 0, simplify);
1606
free_simplify(simplify);
1607
qsort(dir->entries, dir->nr, sizeof(struct dir_entry *), cmp_name);
1608
qsort(dir->ignored, dir->ignored_nr, sizeof(struct dir_entry *), cmp_name);
1773
excludes_file = xdg_path;
1774
}
1775
if (!access_or_warn(path, R_OK, 0))
1674
- add_excludes_from_file(dir, path);
1776
+ add_excludes_from_file_1(dir, path,
1777
+ dir->untracked ? &dir->ss_info_exclude : NULL);
1778
if (excludes_file && !access_or_warn(excludes_file, R_OK, 0))
1676
- add_excludes_from_file(dir, excludes_file);
1779
+ add_excludes_from_file_1(dir, excludes_file,
1780
+ dir->untracked ? &dir->ss_excludes_file : NULL);
1781
}
1782
1783
int remove_path(const char *name)