mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-04 18:58:00 +00:00
fix(discover): keep JVM packages named like build output dirs (#2661)
Below src/<set>/{java,kotlin,scala,groovy}/ every directory is a package,
so a built-in skip name there (target, tmp, vendor, deploy, env, dist...)
is a package name, not build output. Discovery and the inventory filter
now keep such directories; the root itself, its siblings and the safety
core (.git, worktrees) stay skipped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Leonardo trindade miranda <tmonestudio@gmail.com>
This commit is contained in:
1 parent
10ab613de3
commit
259db16da7
4 files changed
+113
-3
No files matched your search
+54
-2
@@ -346,6 +346,56 @@ static bool resolve_global_excludes_path(char *out, size_t out_sz) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* JVM source-set language roots: src/<set>/<lang>/ in Maven and Gradle layouts. */
|
||||
static const char *JVM_SOURCE_LANG_DIRS[] = {"java", "kotlin", "scala", "groovy", NULL};
|
||||
|
||||
static bool component_equals(const char *start, size_t len, const char *word) {
|
||||
return strlen(word) == len && strncmp(start, word, len) == 0;
|
||||
}
|
||||
|
||||
/* True when rel_path names a directory strictly below a JVM source root
|
||||
* ("src/main/java/com/acme/target", "app/src/test/kotlin/x/tmp"). There every
|
||||
* directory is a package, so a built-in skip name such as "target", "tmp" or
|
||||
* "vendor" is an ordinary package name, not build output (#2661). The root
|
||||
* itself and directories beside it ("src/main/target") are not packages. */
|
||||
bool cbm_discover_path_in_jvm_package(const char *rel_path) {
|
||||
if (!rel_path) {
|
||||
return false;
|
||||
}
|
||||
enum { JVM_MAX_COMPONENTS = 256 };
|
||||
const char *starts[JVM_MAX_COMPONENTS];
|
||||
size_t lens[JVM_MAX_COMPONENTS];
|
||||
size_t count = 0;
|
||||
const char *p = rel_path;
|
||||
while (*p && count < JVM_MAX_COMPONENTS) {
|
||||
while (*p == '/' || *p == '\\') {
|
||||
p++;
|
||||
}
|
||||
if (!*p) {
|
||||
break;
|
||||
}
|
||||
const char *start = p;
|
||||
while (*p && *p != '/' && *p != '\\') {
|
||||
p++;
|
||||
}
|
||||
starts[count] = start;
|
||||
lens[count] = (size_t)(p - start);
|
||||
count++;
|
||||
}
|
||||
/* The language root sits at i + 2; the directory must be below it. */
|
||||
for (size_t i = 0; i + 3 < count; i++) {
|
||||
if (!component_equals(starts[i], lens[i], "src")) {
|
||||
continue;
|
||||
}
|
||||
for (int l = 0; JVM_SOURCE_LANG_DIRS[l]; l++) {
|
||||
if (component_equals(starts[i + 2], lens[i + 2], JVM_SOURCE_LANG_DIRS[l])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* True when rel_path equals a suffix rule or ends with "/" + the rule. */
|
||||
bool cbm_discover_path_has_skip_suffix(const char *rel_path) {
|
||||
if (!rel_path) {
|
||||
@@ -803,8 +853,10 @@ static dir_verdict_t directory_verdict(const char *entry_name, const char *rel_p
|
||||
const gitignore_link_t *ignore_chain,
|
||||
const cbm_gitignore_t *global_gi,
|
||||
const cbm_gitignore_t *cbmignore) {
|
||||
if (cbm_should_skip_dir(entry_name, opts ? opts->mode : CBM_MODE_FULL) ||
|
||||
cbm_discover_path_has_skip_suffix(rel_path)) {
|
||||
bool builtin_skip = cbm_should_skip_dir(entry_name, opts ? opts->mode : CBM_MODE_FULL) &&
|
||||
(cbm_discover_is_safety_core_directory(entry_name) ||
|
||||
!cbm_discover_path_in_jvm_package(rel_path));
|
||||
if (builtin_skip || cbm_discover_path_has_skip_suffix(rel_path)) {
|
||||
/* #500: a .cbmignore negation (e.g. "!obj/") whose rule is the last
|
||||
* match for this dir un-skips a built-in skip-list dir — except the
|
||||
* non-negatable safety core. Fall through so .gitignore/global/local
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
/* Pure legacy policy predicates; callers provide live terminated strings. */
|
||||
bool cbm_discover_path_has_skip_suffix(const char *relative_path);
|
||||
bool cbm_discover_is_safety_core_directory(const char *name);
|
||||
bool cbm_discover_path_in_jvm_package(const char *relative_path);
|
||||
|
||||
#endif
|
||||
@@ -102,7 +102,9 @@ static bool cif_directory_reason(cif_context *c, size_t parent, cbm_inventory_pa
|
||||
if (!cif_poll(c)) {
|
||||
return false;
|
||||
}
|
||||
bool builtin = cbm_should_skip_dir(name, CBM_MODE_FULL);
|
||||
bool builtin = cbm_should_skip_dir(name, CBM_MODE_FULL) &&
|
||||
(cbm_discover_is_safety_core_directory(name) ||
|
||||
!cbm_discover_path_in_jvm_package((const char *)path.data));
|
||||
bool suffix = !builtin && cbm_discover_path_has_skip_suffix((const char *)path.data);
|
||||
bool safety =
|
||||
(builtin || suffix) && c->owner->cbm_program && cbm_discover_is_safety_core_directory(name);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "test_framework.h"
|
||||
#include "test_helpers.h"
|
||||
#include "discover/discover.h"
|
||||
#include "discover/discover_policy_internal.h"
|
||||
#include "foundation/platform.h"
|
||||
|
||||
typedef struct {
|
||||
@@ -1328,6 +1329,58 @@ TEST(discover_cbmignore_negates_always_skip_dir) {
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* ── JVM packages named like build output (issue #2661) ─────────── */
|
||||
|
||||
/* Below src/<set>/{java,kotlin,scala,groovy}/ every directory is a package, so
|
||||
* "target", "tmp", "vendor" there are package names, not build output. */
|
||||
TEST(jvm_package_path_predicate_issue2661) {
|
||||
ASSERT_TRUE(cbm_discover_path_in_jvm_package("src/main/java/com/acme/target"));
|
||||
ASSERT_TRUE(cbm_discover_path_in_jvm_package("app/src/test/kotlin/x/tmp"));
|
||||
ASSERT_TRUE(cbm_discover_path_in_jvm_package("src/main/scala/vendor"));
|
||||
/* The language root itself and its siblings are not packages. */
|
||||
ASSERT_FALSE(cbm_discover_path_in_jvm_package("src/main/java"));
|
||||
ASSERT_FALSE(cbm_discover_path_in_jvm_package("src/main/target"));
|
||||
ASSERT_FALSE(cbm_discover_path_in_jvm_package("target"));
|
||||
ASSERT_FALSE(cbm_discover_path_in_jvm_package("module/target/classes"));
|
||||
ASSERT_FALSE(cbm_discover_path_in_jvm_package("src/java/main/tmp"));
|
||||
ASSERT_FALSE(cbm_discover_path_in_jvm_package(NULL));
|
||||
PASS();
|
||||
}
|
||||
|
||||
TEST(discover_keeps_jvm_packages_named_like_build_dirs_issue2661) {
|
||||
char *base = th_mktempdir("cbm_disc_jvm_pkg");
|
||||
ASSERT(base != NULL);
|
||||
|
||||
th_write_file(TH_PATH(base, "src/main/java/com/acme/target/Foo.java"),
|
||||
"package com.acme.target;\nclass Foo {}\n");
|
||||
th_write_file(TH_PATH(base, "src/test/java/com/acme/tmp/T.java"),
|
||||
"package com.acme.tmp;\nclass T {}\n");
|
||||
th_write_file(TH_PATH(base, "src/main/kotlin/com/acme/vendor/V.kt"),
|
||||
"package com.acme.vendor\nclass V\n");
|
||||
/* Real build output stays skipped. */
|
||||
th_write_file(TH_PATH(base, "target/classes/Gen.java"), "class Gen {}\n");
|
||||
th_write_file(TH_PATH(base, "src/main/target/Out.java"), "class Out {}\n");
|
||||
/* The safety core is never un-skipped, even below a package root. */
|
||||
th_write_file(TH_PATH(base, "src/main/java/com/.git/H.java"), "class H {}\n");
|
||||
|
||||
cbm_discover_opts_t opts = {0};
|
||||
cbm_file_info_t *files = NULL;
|
||||
int count = 0;
|
||||
int rc = cbm_discover(base, &opts, &files, &count);
|
||||
ASSERT_EQ(rc, 0);
|
||||
ASSERT_TRUE(discover_has_rel_path(files, count, "src/main/java/com/acme/target/Foo.java"));
|
||||
ASSERT_TRUE(discover_has_rel_path(files, count, "src/test/java/com/acme/tmp/T.java"));
|
||||
ASSERT_TRUE(discover_has_rel_path(files, count, "src/main/kotlin/com/acme/vendor/V.kt"));
|
||||
ASSERT_FALSE(discover_has_rel_path(files, count, "target/classes/Gen.java"));
|
||||
ASSERT_FALSE(discover_has_rel_path(files, count, "src/main/target/Out.java"));
|
||||
ASSERT_FALSE(discover_has_rel_path(files, count, "src/main/java/com/.git/H.java"));
|
||||
ASSERT_EQ(count, 3);
|
||||
|
||||
cbm_discover_free(files, count);
|
||||
th_cleanup(base);
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* ── Laravel compiled Blade view cache (issue #1735) ─────────────── */
|
||||
|
||||
/* storage/framework/views/ holds Laravel's compiled Blade templates: generated
|
||||
@@ -2381,6 +2434,8 @@ SUITE(discover) {
|
||||
RUN_TEST(skip_venv);
|
||||
RUN_TEST(skip_dist);
|
||||
RUN_TEST(skip_target);
|
||||
RUN_TEST(jvm_package_path_predicate_issue2661);
|
||||
RUN_TEST(discover_keeps_jvm_packages_named_like_build_dirs_issue2661);
|
||||
RUN_TEST(skip_vendor);
|
||||
RUN_TEST(skip_vendored);
|
||||
RUN_TEST(skip_terraform);
|
||||
|
||||
Reference in new issue
Block a user