From 44b34e772df975ba00d6af9011eab094a2be963b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 30 Dec 2025 20:19:01 +0000 Subject: [PATCH] fix(backend): Add warnings for local repo index failures When a local git repository connection fails to find any valid repositories, the system now logs warnings instead of failing silently. This helps users diagnose issues with their local repository paths. - Added warning when glob pattern matches no paths - Added warning when paths match but no valid git repos are found - Added info logs to show progress during local repo compilation - Added tests to verify the new warning behavior --- packages/backend/src/repoCompileUtils.test.ts | 124 ++++++++++++++++++ packages/backend/src/repoCompileUtils.ts | 22 ++++ 2 files changed, 146 insertions(+) create mode 100644 packages/backend/src/repoCompileUtils.test.ts diff --git a/packages/backend/src/repoCompileUtils.test.ts b/packages/backend/src/repoCompileUtils.test.ts new file mode 100644 index 00000000..5bb356a5 --- /dev/null +++ b/packages/backend/src/repoCompileUtils.test.ts @@ -0,0 +1,124 @@ +import { expect, test, vi, describe, beforeEach, afterEach } from 'vitest'; +import { compileGenericGitHostConfig_file } from './repoCompileUtils'; + +// Mock the git module +vi.mock('./git.js', () => ({ + isPathAValidGitRepoRoot: vi.fn(), + getOriginUrl: vi.fn(), +})); + +// Mock the glob module +vi.mock('glob', () => ({ + glob: vi.fn(), +})); + +import { isPathAValidGitRepoRoot, getOriginUrl } from './git.js'; +import { glob } from 'glob'; + +const mockedGlob = vi.mocked(glob); +const mockedIsPathAValidGitRepoRoot = vi.mocked(isPathAValidGitRepoRoot); +const mockedGetOriginUrl = vi.mocked(getOriginUrl); + +describe('compileGenericGitHostConfig_file', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + afterEach(() => { + vi.resetAllMocks(); + }); + + test('should return warning when glob pattern matches no paths', async () => { + mockedGlob.mockResolvedValue([]); + + const config = { + type: 'git' as const, + url: 'file:///path/to/nonexistent/repo', + }; + + const result = await compileGenericGitHostConfig_file(config, 1); + + expect(result.repoData).toHaveLength(0); + expect(result.warnings).toHaveLength(1); + expect(result.warnings[0]).toContain('No paths matched the pattern'); + expect(result.warnings[0]).toContain('/path/to/nonexistent/repo'); + }); + + test('should return warning when path is not a valid git repo', async () => { + mockedGlob.mockResolvedValue(['/path/to/not-a-repo']); + mockedIsPathAValidGitRepoRoot.mockResolvedValue(false); + + const config = { + type: 'git' as const, + url: 'file:///path/to/not-a-repo', + }; + + const result = await compileGenericGitHostConfig_file(config, 1); + + expect(result.repoData).toHaveLength(0); + expect(result.warnings.length).toBeGreaterThanOrEqual(1); + expect(result.warnings.some(w => w.includes('not a git repository'))).toBe(true); + expect(result.warnings.some(w => w.includes('No valid git repositories found'))).toBe(true); + }); + + test('should return warning when git repo has no origin url', async () => { + mockedGlob.mockResolvedValue(['/path/to/repo']); + mockedIsPathAValidGitRepoRoot.mockResolvedValue(true); + mockedGetOriginUrl.mockResolvedValue(null); + + const config = { + type: 'git' as const, + url: 'file:///path/to/repo', + }; + + const result = await compileGenericGitHostConfig_file(config, 1); + + expect(result.repoData).toHaveLength(0); + expect(result.warnings.length).toBeGreaterThanOrEqual(1); + expect(result.warnings.some(w => w.includes('remote.origin.url not found'))).toBe(true); + expect(result.warnings.some(w => w.includes('No valid git repositories found'))).toBe(true); + }); + + test('should successfully compile when valid git repo is found', async () => { + mockedGlob.mockResolvedValue(['/path/to/valid/repo']); + mockedIsPathAValidGitRepoRoot.mockResolvedValue(true); + mockedGetOriginUrl.mockResolvedValue('https://github.com/test/repo.git'); + + const config = { + type: 'git' as const, + url: 'file:///path/to/valid/repo', + }; + + const result = await compileGenericGitHostConfig_file(config, 1); + + expect(result.repoData).toHaveLength(1); + expect(result.warnings).toHaveLength(0); + expect(result.repoData[0].cloneUrl).toBe('file:///path/to/valid/repo'); + expect(result.repoData[0].name).toBe('github.com/test/repo'); + }); + + test('should return warnings for invalid repos and success for valid ones', async () => { + mockedGlob.mockResolvedValue(['/path/to/valid/repo', '/path/to/invalid/repo']); + mockedIsPathAValidGitRepoRoot.mockImplementation(async ({ path }) => { + return path === '/path/to/valid/repo'; + }); + mockedGetOriginUrl.mockImplementation(async (path: string) => { + if (path === '/path/to/valid/repo') { + return 'https://github.com/test/repo.git'; + } + return null; + }); + + const config = { + type: 'git' as const, + url: 'file:///path/to/**/repo', + }; + + const result = await compileGenericGitHostConfig_file(config, 1); + + expect(result.repoData).toHaveLength(1); + expect(result.warnings).toHaveLength(1); + expect(result.warnings[0]).toContain('/path/to/invalid/repo'); + expect(result.warnings[0]).toContain('not a git repository'); + }); +}); diff --git a/packages/backend/src/repoCompileUtils.ts b/packages/backend/src/repoCompileUtils.ts index 39ba1347..eab9bafe 100644 --- a/packages/backend/src/repoCompileUtils.ts +++ b/packages/backend/src/repoCompileUtils.ts @@ -479,6 +479,19 @@ export const compileGenericGitHostConfig_file = async ( const repos: RepoData[] = []; const warnings: string[] = []; + // Warn if the glob pattern matched no paths at all + if (repoPaths.length === 0) { + const warning = `No paths matched the pattern '${configUrl.pathname}'. Please verify the path exists and is accessible.`; + logger.warn(warning); + warnings.push(warning); + return { + repoData: repos, + warnings, + }; + } + + logger.info(`Found ${repoPaths.length} path(s) matching pattern '${configUrl.pathname}'`); + await Promise.all(repoPaths.map((repoPath) => gitOperationLimit(async () => { const isGitRepo = await isPathAValidGitRepoRoot({ path: repoPath, @@ -535,6 +548,15 @@ export const compileGenericGitHostConfig_file = async ( repos.push(repo); }))); + // Log summary of results + if (repos.length === 0) { + const warning = `No valid git repositories found from ${repoPaths.length} matched path(s). Check the warnings for details on individual paths.`; + logger.warn(warning); + warnings.push(warning); + } else { + logger.info(`Successfully found ${repos.length} valid git repository(s) from ${repoPaths.length} matched path(s)`); + } + return { repoData: repos, warnings,