|
@@ -129,6 +129,61 @@ export function findNearestCodeGraphRoot(startPath: string): string | null {
|
|
|
return null;
|
|
return null;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * Contents of `.codegraph/.gitignore`. A single wildcard ignore keeps every
|
|
|
|
|
+ * transient file in the index dir — the database, `daemon.pid`, the socket,
|
|
|
|
|
+ * logs, cache, and anything future versions add — out of git, without having
|
|
|
|
|
+ * to enumerate each name (issues #788, #492, #484). Older versions wrote an
|
|
|
|
|
+ * explicit allowlist that never listed `daemon.pid` or the socket, so those
|
|
|
|
|
+ * runtime files were silently committed.
|
|
|
|
|
+ */
|
|
|
|
|
+const GITIGNORE_CONTENT = `# CodeGraph data files — local to each machine, not for committing.
|
|
|
|
|
+# Ignore everything in .codegraph/ except this file itself, so transient
|
|
|
|
|
+# files (the database, daemon.pid, sockets, logs) never show up in git.
|
|
|
|
|
+*
|
|
|
|
|
+!.gitignore
|
|
|
|
|
+`;
|
|
|
|
|
+
|
|
|
|
|
+/** Header line that prefixes every .gitignore CodeGraph has auto-generated. */
|
|
|
|
|
+const GITIGNORE_MARKER = '# CodeGraph data files';
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Is `content` a stale CodeGraph-generated `.gitignore` that should be
|
|
|
|
|
+ * regenerated in place? True when it carries our header but predates the
|
|
|
|
|
+ * wildcard ignore (it has no bare `*` line) — i.e. one of the old explicit
|
|
|
|
|
+ * allowlists (`*.db`, `cache/`, `.dirty`, …) that never ignored `daemon.pid`
|
|
|
|
|
+ * or the socket (issue #788). A file WITHOUT our header is user-authored and
|
|
|
|
|
+ * is left untouched; one that already has the wildcard is current. Matching
|
|
|
|
|
+ * on the header (not a byte-exact list of past defaults) heals every old
|
|
|
|
|
+ * variant — v0.7.x through 0.9.9 — and is idempotent once upgraded.
|
|
|
|
|
+ */
|
|
|
|
|
+function isStaleDefaultGitignore(content: string): boolean {
|
|
|
|
|
+ if (!content.trimStart().startsWith(GITIGNORE_MARKER)) return false;
|
|
|
|
|
+ return !content.split('\n').some((line) => line.trim() === '*');
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Write `.codegraph/.gitignore` if it's absent, or upgrade a stale
|
|
|
|
|
+ * CodeGraph-generated default in place; a user-customized file is left alone.
|
|
|
|
|
+ * Best-effort — returns `false` only if a needed write failed.
|
|
|
|
|
+ */
|
|
|
|
|
+function ensureGitignore(gitignorePath: string): boolean {
|
|
|
|
|
+ let existing: string | null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ existing = fs.readFileSync(gitignorePath, 'utf-8');
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ existing = null; // absent (ENOENT) or unreadable — (re)create below
|
|
|
|
|
+ }
|
|
|
|
|
+ // Current default or a user-authored file: nothing to do.
|
|
|
|
|
+ if (existing !== null && !isStaleDefaultGitignore(existing)) return true;
|
|
|
|
|
+ try {
|
|
|
|
|
+ fs.writeFileSync(gitignorePath, GITIGNORE_CONTENT, 'utf-8');
|
|
|
|
|
+ return true;
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* Create the .codegraph directory structure
|
|
* Create the .codegraph directory structure
|
|
|
* Note: Only throws if codegraph.db already exists, not just if .codegraph/ exists.
|
|
* Note: Only throws if codegraph.db already exists, not just if .codegraph/ exists.
|
|
@@ -146,18 +201,9 @@ export function createDirectory(projectRoot: string): void {
|
|
|
// Create main directory (if it doesn't exist)
|
|
// Create main directory (if it doesn't exist)
|
|
|
fs.mkdirSync(codegraphDir, { recursive: true });
|
|
fs.mkdirSync(codegraphDir, { recursive: true });
|
|
|
|
|
|
|
|
- // Create .gitignore inside .codegraph (if it doesn't exist)
|
|
|
|
|
- const gitignorePath = path.join(codegraphDir, '.gitignore');
|
|
|
|
|
- if (!fs.existsSync(gitignorePath)) {
|
|
|
|
|
- const gitignoreContent = `# CodeGraph data files — local to each machine, not for committing.
|
|
|
|
|
-# Ignore everything in .codegraph/ except this file itself, so transient
|
|
|
|
|
-# files (the database, daemon.pid, sockets, logs) never show up in git.
|
|
|
|
|
-*
|
|
|
|
|
-!.gitignore
|
|
|
|
|
-`;
|
|
|
|
|
-
|
|
|
|
|
- fs.writeFileSync(gitignorePath, gitignoreContent, 'utf-8');
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // Write .gitignore inside .codegraph (create if absent, upgrade a stale
|
|
|
|
|
+ // pre-wildcard default left by an older version — issue #788).
|
|
|
|
|
+ ensureGitignore(path.join(codegraphDir, '.gitignore'));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -296,16 +342,15 @@ export function validateDirectory(projectRoot: string): {
|
|
|
return { valid: false, errors };
|
|
return { valid: false, errors };
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Auto-repair missing .gitignore (non-critical file)
|
|
|
|
|
|
|
+ // Auto-repair / upgrade .gitignore (non-critical file). A missing one is
|
|
|
|
|
+ // recreated; a stale pre-wildcard default that never ignored daemon.pid is
|
|
|
|
|
+ // regenerated in place (issue #788); a user-authored file is left alone.
|
|
|
const gitignorePath = path.join(codegraphDir, '.gitignore');
|
|
const gitignorePath = path.join(codegraphDir, '.gitignore');
|
|
|
- if (!fs.existsSync(gitignorePath)) {
|
|
|
|
|
- try {
|
|
|
|
|
- const gitignoreContent = `# CodeGraph data files — local to each machine, not for committing.\n# Ignore everything in .codegraph/ except this file itself, so transient\n# files (the database, daemon.pid, sockets, logs) never show up in git.\n*\n!.gitignore\n`;
|
|
|
|
|
- fs.writeFileSync(gitignorePath, gitignoreContent, 'utf-8');
|
|
|
|
|
- } catch {
|
|
|
|
|
- // Non-fatal: warn but don't block
|
|
|
|
|
- errors.push('.gitignore missing in .codegraph directory and could not be created');
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const existedBefore = fs.existsSync(gitignorePath);
|
|
|
|
|
+ if (!ensureGitignore(gitignorePath) && !existedBefore) {
|
|
|
|
|
+ // Only a missing-and-uncreatable file is surfaced; a failed in-place
|
|
|
|
|
+ // upgrade of an existing file is non-fatal — the index still works.
|
|
|
|
|
+ errors.push('.gitignore missing in .codegraph directory and could not be created');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
return {
|