MCPcopy Create free account
hub / github.com/Graphify-Labs/graphify / detect

Function detect

graphify/detect.py:1027–1200  ·  view source on GitHub ↗
(root: Path, *, follow_symlinks: bool | None = None, google_workspace: bool | None = None, extra_excludes: list[str] | None = None)

Source from the content-addressed store, hash-verified

1025
1026
1027def detect(root: Path, *, follow_symlinks: bool | None = None, google_workspace: bool | None = None, extra_excludes: list[str] | None = None) -> dict:
1028 root = root.resolve()
1029 if follow_symlinks is None:
1030 follow_symlinks = False
1031 google_workspace = google_workspace_enabled() if google_workspace is None else google_workspace
1032 files: dict[FileType, list[str]] = {
1033 FileType.CODE: [],
1034 FileType.DOCUMENT: [],
1035 FileType.PAPER: [],
1036 FileType.IMAGE: [],
1037 FileType.VIDEO: [],
1038 }
1039 total_words = 0
1040
1041 def _wc(path: Path) -> int:
1042 # Cache word counts against each file's stat signature so unchanged
1043 # PDFs/docx aren't re-parsed on every run just to size the corpus (#1656).
1044 from graphify import cache as _cache
1045 return _cache.cached_word_count(path, root, count_words)
1046
1047 skipped_sensitive: list[str] = []
1048 ignore_patterns = _load_graphifyignore(root)
1049 ignore_cache: dict[Path, bool] = {} # shared across all _is_ignored calls in this scan
1050 # CLI --exclude patterns are anchored at the scan root and appended last
1051 # so they win over any .graphifyignore/.gitignore rules (#947).
1052 if extra_excludes:
1053 for pat in extra_excludes:
1054 line = _parse_gitignore_line(pat)
1055 if line:
1056 ignore_patterns.append((root, line))
1057 include_patterns = _load_graphifyinclude(root)
1058
1059 # Always include graphify-out/memory/ - query results filed back into the graph
1060 memory_dir = root / GRAPHIFY_OUT / "memory"
1061 scan_paths = [root]
1062 if memory_dir.exists():
1063 scan_paths.append(memory_dir)
1064
1065 seen: set[Path] = set()
1066 all_files: list[Path] = []
1067
1068 for scan_root in scan_paths:
1069 in_memory_tree = memory_dir.exists() and str(scan_root).startswith(str(memory_dir))
1070 for dirpath, dirnames, filenames in os.walk(scan_root, followlinks=follow_symlinks):
1071 dp = Path(dirpath)
1072 if follow_symlinks and os.path.islink(dirpath):
1073 real = os.path.realpath(dirpath)
1074 parent_real = os.path.realpath(os.path.dirname(dirpath))
1075 if parent_real == real or parent_real.startswith(real + os.sep):
1076 dirnames.clear()
1077 continue
1078 if not in_memory_tree:
1079 # Prune noise dirs in-place so os.walk never descends into them.
1080 # Dot dirs are allowed — users often want .github/, .claude/, etc.
1081 # Framework caches (.next, .nuxt, …) are caught by _is_noise_dir.
1082 # Negations need no special-casing here: _is_ignored already applies
1083 # last-match-wins (so `!dir/` un-ignores a directory and it won't be
1084 # pruned) and the gitignore parent-exclusion rule (a `!` cannot rescue

Calls 14

google_workspace_enabledFunction · 0.90
_load_graphifyignoreFunction · 0.85
_parse_gitignore_lineFunction · 0.85
_load_graphifyincludeFunction · 0.85
_is_noise_dirFunction · 0.85
_is_ignoredFunction · 0.85
_resolves_under_rootFunction · 0.85
_is_sensitiveFunction · 0.85
classify_fileFunction · 0.85
_wcFunction · 0.85
convert_office_fileFunction · 0.85