read_directory_recursive(): refactor handling of a single path into a separate function
Primarily because I want to reuse it in a separate function later, but this de-dents a huge function by one tabstop which by itself is an improvement as well. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano committed
Jan 8, 2010 at 19:14 UTC
53cc5356fb591d0efa9d2725f8430afe5f5630b5
1 file changed
+90
-63
dir.c
+90
-63
@@ -625,6 +625,84 @@ static int get_dtype(struct dirent *de, const char *path, int len)
625
return dtype;
626
}
627
628
+enum path_treatment {
629
+ path_ignored,
630
+ path_handled,
631
+ path_recurse,
632
+};
633
+
634
+static enum path_treatment treat_path(struct dir_struct *dir,
635
+ struct dirent *de,
636
+ char *path, int path_max,
637
+ int baselen,
638
+ const struct path_simplify *simplify,
639
+ int *len)
640
+{
641
+ int dtype, exclude;
642
+
643
+ if (is_dot_or_dotdot(de->d_name) || !strcmp(de->d_name, ".git"))
644
+ return path_ignored;
645
+ *len = strlen(de->d_name);
646
+ /* Ignore overly long pathnames! */
647
+ if (*len + baselen + 8 > path_max)
648
+ return path_ignored;
649
+ memcpy(path + baselen, de->d_name, *len + 1);
650
+ *len += baselen;
651
+ if (simplify_away(path, *len, simplify))
652
+ return path_ignored;
653
+
654
+ dtype = DTYPE(de);
655
+ exclude = excluded(dir, path, &dtype);
656
+ if (exclude && (dir->flags & DIR_COLLECT_IGNORED)
657
+ && in_pathspec(path, *len, simplify))
658
+ dir_add_ignored(dir, path, *len);
659
+
660
+ /*
661
+ * Excluded? If we don't explicitly want to show
662
+ * ignored files, ignore it
663
+ */
664
+ if (exclude && !(dir->flags & DIR_SHOW_IGNORED))
665
+ return path_ignored;
666
+
667
+ if (dtype == DT_UNKNOWN)
668
+ dtype = get_dtype(de, path, *len);
669
+
670
+ /*
671
+ * Do we want to see just the ignored files?
672
+ * We still need to recurse into directories,
673
+ * even if we don't ignore them, since the
674
+ * directory may contain files that we do..
675
+ */
676
+ if (!exclude && (dir->flags & DIR_SHOW_IGNORED)) {
677
+ if (dtype != DT_DIR)
678
+ return path_ignored;
679
+ }
680
+
681
+ switch (dtype) {
682
+ default:
683
+ return path_ignored;
684
+ case DT_DIR:
685
+ memcpy(path + *len, "/", 2);
686
+ (*len)++;
687
+ switch (treat_directory(dir, path, *len, simplify)) {
688
+ case show_directory:
689
+ if (exclude != !!(dir->flags
690
+ & DIR_SHOW_IGNORED))
691
+ return path_ignored;
692
+ break;
693
+ case recurse_into_directory:
694
+ return path_recurse;
695
+ case ignore_directory:
696
+ return path_ignored;
697
+ }
698
+ break;
699
+ case DT_REG:
700
+ case DT_LNK:
701
+ break;
702
+ }
703
+ return path_handled;
704
+}
705
+
706
/*
707
* Read a directory tree. We currently ignore anything but
708
* directories, regular files and symlinks. That's because git
@@ -634,7 +712,10 @@ static int get_dtype(struct dirent *de, const char *path, int len)
712
* Also, we ignore the name ".git" (even if it is not a directory).
713
* That likely will not change.
714
*/
637
-static int read_directory_recursive(struct dir_struct *dir, const char *base, int baselen, int check_only, const struct path_simplify *simplify)
715
+static int read_directory_recursive(struct dir_struct *dir,
716
+ const char *base, int baselen,
717
+ int check_only,
718
+ const struct path_simplify *simplify)
719
{
720
DIR *fdir = opendir(*base ? base : ".");
721
int contents = 0;
@@ -645,70 +726,16 @@ static int read_directory_recursive(struct dir_struct *dir, const char *base, in
726
memcpy(path, base, baselen);
727
728
while ((de = readdir(fdir)) != NULL) {
648
- int len, dtype;
649
- int exclude;
650
-
651
- if (is_dot_or_dotdot(de->d_name) ||
652
- !strcmp(de->d_name, ".git"))
653
- continue;
654
- len = strlen(de->d_name);
655
- /* Ignore overly long pathnames! */
656
- if (len + baselen + 8 > sizeof(path))
729
+ int len;
730
+ switch (treat_path(dir, de, path, sizeof(path),
731
+ baselen, simplify, &len)) {
732
+ case path_recurse:
733
+ contents += read_directory_recursive
734
+ (dir, path, len, 0, simplify);
735
continue;
658
- memcpy(path + baselen, de->d_name, len+1);
659
- len = baselen + len;
660
- if (simplify_away(path, len, simplify))
736
+ case path_ignored:
737
continue;
662
-
663
- dtype = DTYPE(de);
664
- exclude = excluded(dir, path, &dtype);
665
- if (exclude && (dir->flags & DIR_COLLECT_IGNORED)
666
- && in_pathspec(path, len, simplify))
667
- dir_add_ignored(dir, path,len);
668
-
669
- /*
670
- * Excluded? If we don't explicitly want to show
671
- * ignored files, ignore it
672
- */
673
- if (exclude && !(dir->flags & DIR_SHOW_IGNORED))
674
- continue;
675
-
676
- if (dtype == DT_UNKNOWN)
677
- dtype = get_dtype(de, path, len);
678
-
679
- /*
680
- * Do we want to see just the ignored files?
681
- * We still need to recurse into directories,
682
- * even if we don't ignore them, since the
683
- * directory may contain files that we do..
684
- */
685
- if (!exclude && (dir->flags & DIR_SHOW_IGNORED)) {
686
- if (dtype != DT_DIR)
687
- continue;
688
- }
689
-
690
- switch (dtype) {
691
- default:
692
- continue;
693
- case DT_DIR:
694
- memcpy(path + len, "/", 2);
695
- len++;
696
- switch (treat_directory(dir, path, len, simplify)) {
697
- case show_directory:
698
- if (exclude != !!(dir->flags
699
- & DIR_SHOW_IGNORED))
700
- continue;
701
- break;
702
- case recurse_into_directory:
703
- contents += read_directory_recursive(dir,
704
- path, len, 0, simplify);
705
- continue;
706
- case ignore_directory:
707
- continue;
708
- }
709
- break;
710
- case DT_REG:
711
- case DT_LNK:
738
+ case path_handled:
739
break;
740
}
741
contents++;