mirror of
https://github.com/affaan-m/ECC.git
synced 2026-10-26 18:35:05 +00:00
fix(hooks): use session repository for console warnings
This commit is contained in:
3 files changed
+63
-9
No files matched your search
@@ -28,6 +28,18 @@ const EXCLUDED_PATTERNS = [
|
||||
];
|
||||
|
||||
const MAX_DIRECT_STDIN_BYTES = 16 * 1024 * 1024;
|
||||
|
||||
// This Stop hook inspects the session's working directory. Inherited GIT_*
|
||||
// variables from another Git process can silently redirect discovery and diff
|
||||
// commands to a different repository, so give every Git call the same clean env.
|
||||
function sessionGitOptions() {
|
||||
const env = { ...process.env };
|
||||
for (const name of Object.keys(env)) {
|
||||
if (name.toUpperCase().startsWith('GIT_')) delete env[name];
|
||||
}
|
||||
return { env };
|
||||
}
|
||||
|
||||
let data = '';
|
||||
let stdinBytes = 0;
|
||||
let oversized = false;
|
||||
@@ -62,15 +74,16 @@ function passThroughAndExit() {
|
||||
|
||||
process.stdin.on('end', () => {
|
||||
try {
|
||||
if (!isGitRepo()) {
|
||||
const gitOptions = sessionGitOptions();
|
||||
if (!isGitRepo(gitOptions)) {
|
||||
passThroughAndExit();
|
||||
return;
|
||||
}
|
||||
|
||||
// git reports paths from the repository root, and the session can run in a
|
||||
// subdirectory of it, so read each file from the root.
|
||||
const root = runCommand('git rev-parse --show-toplevel').output;
|
||||
const files = getGitModifiedFiles(['\\.tsx?$', '\\.jsx?$'])
|
||||
const root = runCommand('git rev-parse --show-toplevel', gitOptions).output;
|
||||
const files = getGitModifiedFiles(['\\.tsx?$', '\\.jsx?$'], gitOptions)
|
||||
.filter(f => fs.existsSync(path.join(root, f)))
|
||||
.filter(f => !EXCLUDED_PATTERNS.some(pattern => pattern.test(f)));
|
||||
|
||||
|
||||
@@ -537,23 +537,25 @@ function runCommand(cmd, options = {}) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current directory is a git repository
|
||||
* Check if current directory is a git repository.
|
||||
* @param {object} [options] - Options forwarded to runCommand, including env.
|
||||
*/
|
||||
function isGitRepo() {
|
||||
return runCommand('git rev-parse --git-dir').success;
|
||||
function isGitRepo(options = {}) {
|
||||
return runCommand('git rev-parse --git-dir', options).success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get git modified files, optionally filtered by regex patterns
|
||||
* @param {string[]} patterns - Array of regex pattern strings to filter files.
|
||||
* Invalid patterns are silently skipped.
|
||||
* @param {object} [options] - Options forwarded to every Git subprocess.
|
||||
* @returns {string[]} Array of modified file paths
|
||||
*/
|
||||
function getGitModifiedFiles(patterns = []) {
|
||||
if (!isGitRepo()) return [];
|
||||
function getGitModifiedFiles(patterns = [], options = {}) {
|
||||
if (!isGitRepo(options)) return [];
|
||||
|
||||
// Paths from the repository root even when diff.relative is set.
|
||||
const result = runCommand('git -c diff.relative=false diff --name-only HEAD');
|
||||
const result = runCommand('git -c diff.relative=false diff --name-only HEAD', options);
|
||||
if (!result.success) return [];
|
||||
|
||||
let files = result.output.split('\n').filter(Boolean);
|
||||
|
||||
@@ -1230,6 +1230,45 @@ async function runTests() {
|
||||
passed++;
|
||||
else failed++;
|
||||
|
||||
if (
|
||||
await asyncTest('uses the session repository despite inherited Git environment overrides', async () => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-console-git-env-'));
|
||||
try {
|
||||
const makeRepo = (name, file) => {
|
||||
const repo = path.join(root, name);
|
||||
fs.mkdirSync(path.join(repo, 'src'), { recursive: true });
|
||||
execFileSync('git', ['init', '-q'], { cwd: repo });
|
||||
fs.writeFileSync(path.join(repo, 'src', file), 'export const value = 1;\n');
|
||||
execFileSync('git', ['add', '-A'], { cwd: repo });
|
||||
execFileSync('git', ['-c', 'user.email=t@t.local', '-c', 'user.name=t', '-c', 'commit.gpgsign=false', 'commit', '-q', '-m', 'seed'], { cwd: repo });
|
||||
return repo;
|
||||
};
|
||||
const sessionRepo = makeRepo('session', 'local.ts');
|
||||
const foreignRepo = makeRepo('foreign', 'foreign.ts');
|
||||
fs.writeFileSync(path.join(foreignRepo, 'src', 'foreign.ts'), 'console.log("foreign");\n');
|
||||
const env = {
|
||||
GIT_DIR: path.join(foreignRepo, '.git'),
|
||||
GIT_WORK_TREE: foreignRepo,
|
||||
GIT_INDEX_FILE: path.join(foreignRepo, '.git', 'index')
|
||||
};
|
||||
|
||||
const clean = await runScript(path.join(scriptsDir, 'check-console-log.js'), '{}', env, sessionRepo);
|
||||
assert.strictEqual(clean.code, 0);
|
||||
assert.ok(!clean.stderr.includes('console.log found'), `foreign repository leaked into hook: ${clean.stderr}`);
|
||||
|
||||
fs.writeFileSync(path.join(sessionRepo, 'src', 'local.ts'), 'console.log("local");\n');
|
||||
const local = await runScript(path.join(scriptsDir, 'check-console-log.js'), '{}', env, sessionRepo);
|
||||
assert.strictEqual(local.code, 0);
|
||||
assert.ok(local.stderr.includes('console.log found in src/local.ts'), local.stderr);
|
||||
assert.ok(!local.stderr.includes('foreign.ts'), local.stderr);
|
||||
} finally {
|
||||
fs.rmSync(root, { recursive: true, force: true });
|
||||
}
|
||||
})
|
||||
)
|
||||
passed++;
|
||||
else failed++;
|
||||
|
||||
// session-end.js tests
|
||||
console.log('\nsession-end.js:');
|
||||
|
||||
|
||||
Reference in new issue
Block a user