dir.c: optionally compute sha-1 of a .gitignore file

This is not used anywhere yet. But the goal is to compare quickly if a .gitignore file has changed when we have the SHA-1 of both old (cached somewhere) and new (from index or a tree) versions. Helped-by: Junio C Hamano <gitster@pobox.com> Helped-by: Torsten Bögershausen <tboegi@web.de> 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 55fe6f51f41f254d3d87994d18bff04664aa013b
2 files changed +53 -7
dir.c
+47 -7
@@ -466,7 +466,8 @@ void add_exclude(const char *string, const char *base,
466 x->el = el;
467 }
468
469 -static void *read_skip_worktree_file_from_index(const char *path, size_t *size)
469 +static void *read_skip_worktree_file_from_index(const char *path, size_t *size,
470 + struct sha1_stat *sha1_stat)
471 {
472 int pos, len;
473 unsigned long sz;
@@ -485,6 +486,10 @@ static void *read_skip_worktree_file_from_index(const char *path, size_t *size)
486 return NULL;
487 }
488 *size = xsize_t(sz);
489 + if (sha1_stat) {
490 + memset(&sha1_stat->stat, 0, sizeof(sha1_stat->stat));
491 + hashcpy(sha1_stat->sha1, active_cache[pos]->sha1);
492 + }
493 return data;
494 }
495
@@ -529,11 +534,18 @@ static void trim_trailing_spaces(char *buf)
534 *last_space = '\0';
535 }
536
532 -int add_excludes_from_file_to_list(const char *fname,
533 - const char *base,
534 - int baselen,
535 - struct exclude_list *el,
536 - int check_index)
537 +/*
538 + * Given a file with name "fname", read it (either from disk, or from
539 + * the index if "check_index" is non-zero), parse it and store the
540 + * exclude rules in "el".
541 + *
542 + * If "ss" is not NULL, compute SHA-1 of the exclude file and fill
543 + * stat data from disk (only valid if add_excludes returns zero). If
544 + * ss_valid is non-zero, "ss" must contain good value as input.
545 + */
546 +static int add_excludes(const char *fname, const char *base, int baselen,
547 + struct exclude_list *el, int check_index,
548 + struct sha1_stat *sha1_stat)
549 {
550 struct stat st;
551 int fd, i, lineno = 1;
@@ -547,7 +559,7 @@ int add_excludes_from_file_to_list(const char *fname,
559 if (0 <= fd)
560 close(fd);
561 if (!check_index ||
550 - (buf = read_skip_worktree_file_from_index(fname, &size)) == NULL)
562 + (buf = read_skip_worktree_file_from_index(fname, &size, sha1_stat)) == NULL)
563 return -1;
564 if (size == 0) {
565 free(buf);
@@ -560,6 +572,11 @@ int add_excludes_from_file_to_list(const char *fname,
572 } else {
573 size = xsize_t(st.st_size);
574 if (size == 0) {
575 + if (sha1_stat) {
576 + fill_stat_data(&sha1_stat->stat, &st);
577 + hashcpy(sha1_stat->sha1, EMPTY_BLOB_SHA1_BIN);
578 + sha1_stat->valid = 1;
579 + }
580 close(fd);
581 return 0;
582 }
@@ -571,6 +588,22 @@ int add_excludes_from_file_to_list(const char *fname,
588 }
589 buf[size++] = '\n';
590 close(fd);
591 + if (sha1_stat) {
592 + int pos;
593 + if (sha1_stat->valid &&
594 + !match_stat_data(&sha1_stat->stat, &st))
595 + ; /* no content change, ss->sha1 still good */
596 + else if (check_index &&
597 + (pos = cache_name_pos(fname, strlen(fname))) >= 0 &&
598 + !ce_stage(active_cache[pos]) &&
599 + ce_uptodate(active_cache[pos]) &&
600 + !would_convert_to_git(fname))
601 + hashcpy(sha1_stat->sha1, active_cache[pos]->sha1);
602 + else
603 + hash_sha1_file(buf, size, "blob", sha1_stat->sha1);
604 + fill_stat_data(&sha1_stat->stat, &st);
605 + sha1_stat->valid = 1;
606 + }
607 }
608
609 el->filebuf = buf;
@@ -589,6 +622,13 @@ int add_excludes_from_file_to_list(const char *fname,
622 return 0;
623 }
624
625 +int add_excludes_from_file_to_list(const char *fname, const char *base,
626 + int baselen, struct exclude_list *el,
627 + int check_index)
628 +{
629 + return add_excludes(fname, base, baselen, el, check_index, NULL);
630 +}
631 +
632 struct exclude_list *add_exclude_list(struct dir_struct *dir,
633 int group_type, const char *src)
634 {
dir.h
+6
@@ -73,6 +73,12 @@ struct exclude_list_group {
73 struct exclude_list *el;
74 };
75
76 +struct sha1_stat {
77 + struct stat_data stat;
78 + unsigned char sha1[20];
79 + int valid;
80 +};
81 +
82 struct dir_struct {
83 int nr, alloc;
84 int ignored_nr, ignored_alloc;