mcp-vector-search 0.7.5__py3-none-any.whl → 0.8.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mcp-vector-search might be problematic. Click here for more details.

@@ -102,16 +102,18 @@ class GitignoreParser:
102
102
  self._load_gitignore_files()
103
103
 
104
104
  def _load_gitignore_files(self) -> None:
105
- """Load all .gitignore files in the project hierarchy."""
106
- # Load global .gitignore first (if exists)
107
- global_gitignore = self.project_root / ".gitignore"
108
- if global_gitignore.exists():
109
- self._parse_gitignore_file(global_gitignore)
105
+ """Load .gitignore file from project root only.
110
106
 
111
- # Load .gitignore files in subdirectories
112
- for gitignore_file in self.project_root.rglob(".gitignore"):
113
- if gitignore_file != global_gitignore:
114
- self._parse_gitignore_file(gitignore_file)
107
+ Note: Only the root .gitignore is loaded to avoid performance issues
108
+ with rglob traversing large directory trees (e.g., node_modules with
109
+ 250K+ files). Subdirectory .gitignore files are intentionally skipped
110
+ as they would add significant overhead without much benefit for
111
+ semantic code search indexing.
112
+ """
113
+ # Load root .gitignore only
114
+ root_gitignore = self.project_root / ".gitignore"
115
+ if root_gitignore.exists():
116
+ self._parse_gitignore_file(root_gitignore)
115
117
 
116
118
  def _parse_gitignore_file(self, gitignore_path: Path) -> None:
117
119
  """Parse a single .gitignore file.
@@ -136,32 +138,32 @@ class GitignoreParser:
136
138
  # Check for directory-only pattern
137
139
  is_directory_only = line.endswith("/")
138
140
 
139
- # Create pattern relative to the .gitignore file's directory
140
- gitignore_dir = gitignore_path.parent
141
- if gitignore_dir != self.project_root:
142
- # Adjust pattern for subdirectory .gitignore files
143
- relative_dir = gitignore_dir.relative_to(self.project_root)
144
- if not line.startswith("/") and not is_negation:
145
- line = str(relative_dir / line)
146
- elif is_negation and not line[1:].startswith("/"):
147
- line = "!" + str(relative_dir / line[1:])
148
-
141
+ # Create pattern (all patterns are from root .gitignore)
149
142
  pattern = GitignorePattern(line, is_negation, is_directory_only)
150
143
  self.patterns.append(pattern)
151
144
 
152
145
  except Exception as e:
153
146
  logger.warning(f"Failed to parse {gitignore_path}: {e}")
154
147
 
155
- def is_ignored(self, path: Path) -> bool:
148
+ def is_ignored(self, path: Path, is_directory: bool | None = None) -> bool:
156
149
  """Check if a path should be ignored according to .gitignore rules.
157
150
 
158
151
  Args:
159
152
  path: Path to check (can be absolute or relative to project root)
153
+ is_directory: Optional hint if path is a directory.
154
+ If None, will check filesystem (slower).
155
+ If provided, skips filesystem check (faster).
160
156
 
161
157
  Returns:
162
158
  True if the path should be ignored
163
159
  """
164
160
  try:
161
+ # SHORT-CIRCUIT: If no patterns, nothing is ignored
162
+ # This prevents 200k+ unnecessary filesystem stat() calls on projects
163
+ # without .gitignore files
164
+ if not self.patterns:
165
+ return False
166
+
165
167
  # Convert to relative path from project root
166
168
  if path.is_absolute():
167
169
  relative_path = path.relative_to(self.project_root)
@@ -169,7 +171,12 @@ class GitignoreParser:
169
171
  relative_path = path
170
172
 
171
173
  path_str = str(relative_path).replace("\\", "/")
172
- is_directory = path.is_dir() if path.exists() else False
174
+
175
+ # Only check if directory when needed and not provided as hint
176
+ # PERFORMANCE: Passing is_directory hint from caller (e.g., os.walk)
177
+ # avoids hundreds of thousands of stat() calls on large repositories
178
+ if is_directory is None:
179
+ is_directory = path.is_dir() if path.exists() else False
173
180
 
174
181
  # Apply patterns in order, with later patterns overriding earlier ones
175
182
  ignored = False
@@ -216,15 +223,16 @@ def create_gitignore_parser(project_root: Path) -> GitignoreParser:
216
223
  return GitignoreParser(project_root)
217
224
 
218
225
 
219
- def is_path_gitignored(path: Path, project_root: Path) -> bool:
226
+ def is_path_gitignored(path: Path, project_root: Path, is_directory: bool | None = None) -> bool:
220
227
  """Quick function to check if a path is gitignored.
221
228
 
222
229
  Args:
223
230
  path: Path to check
224
231
  project_root: Root directory of the project
232
+ is_directory: Optional hint if path is a directory (avoids filesystem check)
225
233
 
226
234
  Returns:
227
235
  True if the path should be ignored
228
236
  """
229
237
  parser = create_gitignore_parser(project_root)
230
- return parser.is_ignored(path)
238
+ return parser.is_ignored(path, is_directory=is_directory)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-vector-search
3
- Version: 0.7.5
3
+ Version: 0.8.0
4
4
  Summary: CLI-first semantic code search with MCP integration
5
5
  Project-URL: Homepage, https://github.com/bobmatnyc/mcp-vector-search
6
6
  Project-URL: Documentation, https://mcp-vector-search.readthedocs.io
@@ -1,24 +1,25 @@
1
- mcp_vector_search/__init__.py,sha256=dZBJd61xdNTaijMxlEUMhBGLWPSCGNuFPxIzXBRWJ68,299
1
+ mcp_vector_search/__init__.py,sha256=j0J6-76f4J8zJJka6ztBM3ah039ges62kwsejscnarc,299
2
2
  mcp_vector_search/py.typed,sha256=lCKeV9Qcn9sGtbRsgg-LJO2ZwWRuknnnlmomq3bJFH0,43
3
3
  mcp_vector_search/cli/__init__.py,sha256=TNB7CaOASz8u3yHWLbNmo8-GtHF0qwUjVKWAuNphKgo,40
4
4
  mcp_vector_search/cli/didyoumean.py,sha256=F_ss-EX4F9RgnMsEhdTwLpyNCah9SqnBZc2tBtzASck,15918
5
5
  mcp_vector_search/cli/export.py,sha256=iluxuRT2KELdKlQeDAlVkteiel4GGrng153UAw9H0as,10804
6
6
  mcp_vector_search/cli/history.py,sha256=6wRrSfxpUe9hJXuaEeVxOVkFlcpqkIiGfwzDgd5N6c8,9323
7
7
  mcp_vector_search/cli/interactive.py,sha256=T7P4dAdvbglznzQYgiePv5YNyOx9FeE57Y3OKYnnbYE,12744
8
- mcp_vector_search/cli/main.py,sha256=5UnZufgKBUSMgxe7WDIl5tYI8fEONf1jNnhFjBvsnW0,14509
8
+ mcp_vector_search/cli/main.py,sha256=oFyuocKZK9fN4XY1xejPgI3lMo4E0dplJ4SasfLZluo,14770
9
9
  mcp_vector_search/cli/output.py,sha256=7ShIk_UKzhDzRGxI6JluPu0gGkbmKOevqgIAKR4oCa0,12560
10
10
  mcp_vector_search/cli/suggestions.py,sha256=h-UaxoLcHmFbhZSm0WG7nKJXAIRIqhv7aGsXijp7vA8,13273
11
11
  mcp_vector_search/cli/commands/__init__.py,sha256=vQls-YKZ54YEwmf7g1dL0T2SS9D4pdQljXzsUChG_V4,42
12
12
  mcp_vector_search/cli/commands/auto_index.py,sha256=imVVbxWRlA128NPdK9BetNNl3ELrsdq-hqcsLqyAmoM,12712
13
13
  mcp_vector_search/cli/commands/config.py,sha256=mKE8gUgAOqCM__4yzEEu9HJPbx9X15lN264zkDJBRxg,12399
14
- mcp_vector_search/cli/commands/demo.py,sha256=HOa5g4vDu_zjSq77bMcFaCck7RN9YsYgsIknAfeYIC8,10683
15
- mcp_vector_search/cli/commands/index.py,sha256=tqn6KjDygAHam5mINthYFBm-hA6I8QYDjrSVRmUtXLE,18213
14
+ mcp_vector_search/cli/commands/demo.py,sha256=MVfEkYmA2abRFwAbk-lpa6P14_SLJBHZAuHb9d6d02U,10630
15
+ mcp_vector_search/cli/commands/index.py,sha256=K_5gmmgclfkyXDvucBPdnvbYzyfa53eVbPdkuWiqZUk,22106
16
16
  mcp_vector_search/cli/commands/init.py,sha256=2kdjtIPPeutKUXs65-6W1VQPF_BQrbV6_U3TCE7U5mw,23242
17
17
  mcp_vector_search/cli/commands/install.py,sha256=phk7Eb7UOU5IsRfJyaDPdOfdUWli9gyA4cHjhgXcNEI,24609
18
- mcp_vector_search/cli/commands/mcp.py,sha256=LGk9AfQ8d3QOl38u7LnTLOq6tR1DLah_X0ZuzCBNhYI,38606
18
+ mcp_vector_search/cli/commands/mcp.py,sha256=Mk4g43R9yRiJVMxsDFUsZldKqY0yi2coQmhAqIMPklo,38958
19
19
  mcp_vector_search/cli/commands/reset.py,sha256=bsIT6zjDf6gsvIkVaRaUClYzlTyNe--8t0NWkBY0ldU,13724
20
20
  mcp_vector_search/cli/commands/search.py,sha256=yyou7wO9qZ_w2oiKdyOrk2WUxvkFpc-Up8hpflxYlyw,24802
21
- mcp_vector_search/cli/commands/status.py,sha256=7ro6M3aifV0cuCqqxJ278P9g-fbhzvjoOABUoitMrPo,18929
21
+ mcp_vector_search/cli/commands/status.py,sha256=sa_0QHioCmPF5A7obqV2ls-9kmX_JYo7nq3XUe1dmrg,19630
22
+ mcp_vector_search/cli/commands/visualize.py,sha256=vlTYgcepIFWFAe8LAXvZiV5OSLM2JzinYR-k0D0-5K4,16349
22
23
  mcp_vector_search/cli/commands/watch.py,sha256=2pyWRoo4fIppFnyQ4sW4IBLHmpb_IwnTjRnzHkVBPcQ,8927
23
24
  mcp_vector_search/config/__init__.py,sha256=r_qAQkU5gc0EQ2pv8EQARACe4klhrR_WRJqCb9lfGc0,54
24
25
  mcp_vector_search/config/constants.py,sha256=afXR6SvLLd8QYY4MG4s1vq-hCJiQsE5PhnE-XG9lvb4,1092
@@ -27,14 +28,14 @@ mcp_vector_search/config/settings.py,sha256=m8o8j-tvWcuzrnNL6YWbi2fFbcB3lZY1kMNi
27
28
  mcp_vector_search/core/__init__.py,sha256=bWKtKmmaFs7gG5XPCbrx77UYIVeO1FF8wIJxpj1dLNw,48
28
29
  mcp_vector_search/core/auto_indexer.py,sha256=0S4lZXaUgqEytMSA2FxQsh5hN7V1mbSLYVzEf_dslYQ,10307
29
30
  mcp_vector_search/core/connection_pool.py,sha256=Yo-gUQQbHawtuvh6OcJiAlbbvWQGQBd31QZOvs498fg,11224
30
- mcp_vector_search/core/database.py,sha256=fMcclsO2dGOfsUSN38rJDRGVNEuPvGKHZlSSuuyIKag,35512
31
+ mcp_vector_search/core/database.py,sha256=wmrnlyWvNH1jr4Rx_b6OjxAeUQ-33G3Vj6v_lji2Eik,37705
31
32
  mcp_vector_search/core/embeddings.py,sha256=wSMUNxZcuGPMxxQ1AbKqA1a3-0c6AiOqmuuI7OqTyaQ,10578
32
33
  mcp_vector_search/core/exceptions.py,sha256=3bCjT8wmrLz_0e_Tayr90049zNTKYFWZa19kl0saKz8,1597
33
34
  mcp_vector_search/core/factory.py,sha256=tM6Ft-V9buF7nn9xbRMU1ngji-BJOKt6BhtfQhFLmF4,10384
34
35
  mcp_vector_search/core/git_hooks.py,sha256=xOfPpzgKoNTwM-vbhAihUucgudBQk45bCAVR5zJOFlQ,10878
35
- mcp_vector_search/core/indexer.py,sha256=MlsMDcGvl1ww6wAtCeTVU5AkaBM-z2LP4HGXErKoDHM,18331
36
- mcp_vector_search/core/models.py,sha256=fnZxvUkd9Afxmdwtw2BJX7uik6rQTwuWBTTqTeqDi0A,6697
37
- mcp_vector_search/core/project.py,sha256=RNeLBZZw6SO5mXqCwYfhStTGuVgeMq1US5UftG0SBYk,10069
36
+ mcp_vector_search/core/indexer.py,sha256=NdIYVtD5D21ej9_RRypKq-UKjpGXTXiDXskhzdYHUCQ,28440
37
+ mcp_vector_search/core/models.py,sha256=h54wTwwXR5qU-YOVi8q8NEFmpnQfC4S0ER2mMJqn4bk,8512
38
+ mcp_vector_search/core/project.py,sha256=l81uc5B4CB8VXDbcHzF-_CagxIERDh23tH0iNqTePTs,10403
38
39
  mcp_vector_search/core/scheduler.py,sha256=PBSlu-ieDYCXOMGYY7QKv9UReFEDPHNmwnUv_xb4vxg,11761
39
40
  mcp_vector_search/core/search.py,sha256=9OC8-KwWdbw4y4QPQ-VXfz0encVHTJWYLtah3_chqG8,33682
40
41
  mcp_vector_search/core/watcher.py,sha256=-DFRCnuUfcqcTrkZPQqfJSvxKAxnpt-axgEj1V-B0O4,10862
@@ -42,22 +43,22 @@ mcp_vector_search/mcp/__init__.py,sha256=gfKR0QV7Jqvj5y0LMBe9gSghd5_rPsvm_rml0ry
42
43
  mcp_vector_search/mcp/__main__.py,sha256=KgwB59HM5pRLe2Aj-fvDFcTp95lyT0wfmS3ENcx9gPc,571
43
44
  mcp_vector_search/mcp/server.py,sha256=YmHyvJqg_CjxEN356ShFrTPLgDKzaLXyrt8tNHVryEY,28322
44
45
  mcp_vector_search/parsers/__init__.py,sha256=jr0Yqz1xMok4lnG7_aXnkZThGuefrlAj8PWVbfeT3QQ,228
45
- mcp_vector_search/parsers/base.py,sha256=kOurwRR4xlyIje9rHLlEVa-OCl1LK8ih_fAFWHFg78g,5395
46
+ mcp_vector_search/parsers/base.py,sha256=KS0bJeGoZamdqGS7KdAOGFxO_P_-TsjrlBnuzeu8B5U,8768
46
47
  mcp_vector_search/parsers/dart.py,sha256=li2JP0vwpSsZnMNq0PweZCD_o-y1jUwubHlSA8nm8KQ,21816
47
48
  mcp_vector_search/parsers/html.py,sha256=nzEVDV4oCBp3wpL8vp6WWx5eqiB39agu9E048JkuRJQ,13010
48
- mcp_vector_search/parsers/javascript.py,sha256=P7fT_tXCzUuXATTkTx_DyD4EuG0_KjIDlay09MhkKTE,9824
49
+ mcp_vector_search/parsers/javascript.py,sha256=WlEBDr773TM4D6KNpHQq93vtbzZ7xtXWNkOivLGMsAE,23386
49
50
  mcp_vector_search/parsers/php.py,sha256=1QjnE8SAQF86VQ7pNfn1Pmpg5Dni4M7KCLU7212DkXM,24774
50
- mcp_vector_search/parsers/python.py,sha256=IB4gQ6DD6Oqvws5p3LQtHTJOtmH6f9FWmO9fQRfGQx4,15688
51
+ mcp_vector_search/parsers/python.py,sha256=1KwubEIpyxHPCnlxN8EMb745A14JJ7J4YO2iVOeuHfs,19092
51
52
  mcp_vector_search/parsers/registry.py,sha256=L00EUp58ff_xatgQW-cBvE0AVBQi7cGtvr6zWV_NYbc,6457
52
53
  mcp_vector_search/parsers/ruby.py,sha256=xNn_z8txAWL7E1ULcFMiqn5idFhf5GQn8N3x1yE-c2k,23818
53
54
  mcp_vector_search/parsers/text.py,sha256=jvMdFspbmrrOR1GSGzf2gvBDCXz1cPN_xemoDK4fUvM,6084
54
55
  mcp_vector_search/parsers/utils.py,sha256=10vT-GJSeDUoGSIslz8zq4RyavFiMtizCmcnn9cbQqE,8103
55
56
  mcp_vector_search/utils/__init__.py,sha256=Eq6lY-oPMfCt-GpPUbg9QbmTHuQVmTaVDBMU2183KVw,887
56
- mcp_vector_search/utils/gitignore.py,sha256=bzie3V5gOGIN7j3FNVLLCx8O_hfZJDUqqAy5T3lT3Ek,7685
57
+ mcp_vector_search/utils/gitignore.py,sha256=GiHQu9kv9PRLsWuNS8kbpXsTaBdhlsSHTu1NrZ8Ug5Y,8162
57
58
  mcp_vector_search/utils/timing.py,sha256=THC7mfbTYnUpnnDcblgQacYMzbEkfFoIShx6plmhCgg,11285
58
59
  mcp_vector_search/utils/version.py,sha256=d7fS-CLemxb8UzZ9j18zH0Y0Ud097ljKKYYOPulnGPE,1138
59
- mcp_vector_search-0.7.5.dist-info/METADATA,sha256=7K-LZqTr2XyHrFVwuUBGM0AxKku3b-a0HEWNkUTnYMo,19120
60
- mcp_vector_search-0.7.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
61
- mcp_vector_search-0.7.5.dist-info/entry_points.txt,sha256=y3Ygtc_JiBchNEIL-tPABo7EbzBExGAxwGdkkeP5D2I,86
62
- mcp_vector_search-0.7.5.dist-info/licenses/LICENSE,sha256=FqZUgGJH_tZKZLQsMCpXaLawRyLmyFKRVfMwYyEcyTs,1072
63
- mcp_vector_search-0.7.5.dist-info/RECORD,,
60
+ mcp_vector_search-0.8.0.dist-info/METADATA,sha256=8ZdCNZR0sEfaPSKZLINETw7M_4zLHU6dO9LiieUh4uA,19120
61
+ mcp_vector_search-0.8.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
62
+ mcp_vector_search-0.8.0.dist-info/entry_points.txt,sha256=y3Ygtc_JiBchNEIL-tPABo7EbzBExGAxwGdkkeP5D2I,86
63
+ mcp_vector_search-0.8.0.dist-info/licenses/LICENSE,sha256=FqZUgGJH_tZKZLQsMCpXaLawRyLmyFKRVfMwYyEcyTs,1072
64
+ mcp_vector_search-0.8.0.dist-info/RECORD,,