mirror of
https://github.com/yamadashy/repomix.git
synced 2025-06-11 00:25:54 +03:00
# Conflicts: # src/core/packager.ts # src/core/security/securityCheck.ts # src/shared/processConcurrency.ts # Conflicts: # package-lock.json # package.json
227 lines
6.7 KiB
TypeScript
227 lines
6.7 KiB
TypeScript
import * as fs from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
import process from 'node:process';
|
|
import { globby } from 'globby';
|
|
import { minimatch } from 'minimatch';
|
|
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
|
import {
|
|
getIgnoreFilePatterns,
|
|
getIgnorePatterns,
|
|
parseIgnoreContent,
|
|
searchFiles,
|
|
} from '../../../src/core/file/fileSearch.js';
|
|
import { createMockConfig, isWindows } from '../../testing/testUtils.js';
|
|
|
|
vi.mock('fs/promises');
|
|
vi.mock('globby');
|
|
|
|
describe('fileSearch', () => {
|
|
beforeEach(() => {
|
|
vi.resetAllMocks();
|
|
});
|
|
|
|
describe('getIgnoreFilePaths', () => {
|
|
test('should return correct paths when .gitignore and .repomixignore exist', async () => {
|
|
vi.mocked(fs.access).mockResolvedValue(undefined);
|
|
const mockConfig = createMockConfig({
|
|
ignore: {
|
|
useGitignore: true,
|
|
useDefaultPatterns: true,
|
|
customPatterns: [],
|
|
},
|
|
});
|
|
const filePatterns = await getIgnoreFilePatterns(mockConfig);
|
|
expect(filePatterns).toEqual(['**/.gitignore', '**/.repomixignore']);
|
|
});
|
|
|
|
test('should not include .gitignore when useGitignore is false', async () => {
|
|
vi.mocked(fs.access).mockResolvedValue(undefined);
|
|
const mockConfig = createMockConfig({
|
|
ignore: {
|
|
useGitignore: false,
|
|
useDefaultPatterns: true,
|
|
customPatterns: [],
|
|
},
|
|
});
|
|
const filePatterns = await getIgnoreFilePatterns(mockConfig);
|
|
expect(filePatterns).toEqual(['**/.repomixignore']);
|
|
});
|
|
});
|
|
|
|
describe('getIgnorePatterns', () => {
|
|
test('should return default patterns when useDefaultPatterns is true', async () => {
|
|
const mockConfig = createMockConfig({
|
|
ignore: {
|
|
useGitignore: true,
|
|
useDefaultPatterns: true,
|
|
customPatterns: [],
|
|
},
|
|
});
|
|
|
|
const patterns = await getIgnorePatterns(process.cwd(), mockConfig);
|
|
|
|
expect(patterns.length).toBeGreaterThan(0);
|
|
expect(patterns).toContain('**/node_modules/**');
|
|
});
|
|
|
|
test('should include custom patterns', async () => {
|
|
const mockConfig = createMockConfig({
|
|
ignore: {
|
|
useGitignore: true,
|
|
useDefaultPatterns: false,
|
|
customPatterns: ['*.custom', 'temp/'],
|
|
},
|
|
});
|
|
|
|
const patterns = await getIgnorePatterns(process.cwd(), mockConfig);
|
|
|
|
expect(patterns).toEqual(['repomix-output.txt', '*.custom', 'temp/']);
|
|
});
|
|
|
|
test('should combine default and custom patterns', async () => {
|
|
const mockConfig = createMockConfig({
|
|
ignore: {
|
|
useGitignore: true,
|
|
useDefaultPatterns: true,
|
|
customPatterns: ['*.custom', 'temp/'],
|
|
},
|
|
});
|
|
|
|
const patterns = await getIgnorePatterns(process.cwd(), mockConfig);
|
|
|
|
expect(patterns).toContain('**/node_modules/**');
|
|
expect(patterns).toContain('*.custom');
|
|
expect(patterns).toContain('temp/');
|
|
});
|
|
});
|
|
|
|
describe('parseIgnoreContent', () => {
|
|
test('should correctly parse ignore content', () => {
|
|
const content = `
|
|
# Comment
|
|
node_modules
|
|
*.log
|
|
|
|
.DS_Store
|
|
`;
|
|
|
|
const patterns = parseIgnoreContent(content);
|
|
|
|
expect(patterns).toEqual(['node_modules', '*.log', '.DS_Store']);
|
|
});
|
|
|
|
test('should handle mixed line endings', () => {
|
|
const content = 'node_modules\n*.log\r\n.DS_Store\r';
|
|
|
|
const patterns = parseIgnoreContent(content);
|
|
|
|
expect(patterns).toEqual(['node_modules', '*.log', '.DS_Store']);
|
|
});
|
|
});
|
|
|
|
describe('filterFiles', () => {
|
|
beforeEach(() => {
|
|
vi.resetAllMocks();
|
|
});
|
|
|
|
test('should call globby with correct parameters', async () => {
|
|
const mockConfig = createMockConfig({
|
|
include: ['**/*.js'],
|
|
ignore: {
|
|
useGitignore: true,
|
|
useDefaultPatterns: false,
|
|
customPatterns: ['*.custom'],
|
|
},
|
|
});
|
|
|
|
vi.mocked(globby).mockResolvedValue(['file1.js', 'file2.js']);
|
|
vi.mocked(fs.access).mockResolvedValue(undefined);
|
|
|
|
await searchFiles('/mock/root', mockConfig);
|
|
|
|
expect(globby).toHaveBeenCalledWith(
|
|
['**/*.js'],
|
|
expect.objectContaining({
|
|
cwd: '/mock/root',
|
|
ignore: expect.arrayContaining(['*.custom']),
|
|
ignoreFiles: expect.arrayContaining(['**/.gitignore', '**/.repomixignore']),
|
|
onlyFiles: true,
|
|
absolute: false,
|
|
dot: true,
|
|
followSymbolicLinks: false,
|
|
}),
|
|
);
|
|
});
|
|
|
|
test.runIf(!isWindows)('Honor .gitignore files in subdirectories', async () => {
|
|
const mockConfig = createMockConfig({
|
|
include: ['**/*.js'],
|
|
ignore: {
|
|
useGitignore: true,
|
|
useDefaultPatterns: false,
|
|
customPatterns: [],
|
|
},
|
|
});
|
|
|
|
const mockFileStructure = [
|
|
'root/file1.js',
|
|
'root/subdir/file2.js',
|
|
'root/subdir/ignored.js',
|
|
'root/another/file3.js',
|
|
];
|
|
|
|
const mockGitignoreContent = {
|
|
'/mock/root/.gitignore': '*.log',
|
|
'/mock/root/subdir/.gitignore': 'ignored.js',
|
|
};
|
|
|
|
vi.mocked(globby).mockImplementation(async () => {
|
|
// Simulate filtering files based on .gitignore
|
|
return mockFileStructure.filter((file) => {
|
|
const relativePath = file.replace('root/', '');
|
|
const dir = path.dirname(relativePath);
|
|
const gitignorePath = path.join('/mock/root', dir, '.gitignore');
|
|
const gitignoreContent = mockGitignoreContent[gitignorePath as keyof typeof mockGitignoreContent];
|
|
if (gitignoreContent && minimatch(path.basename(file), gitignoreContent)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
});
|
|
|
|
vi.mocked(fs.readFile).mockImplementation(async (filePath) => {
|
|
return mockGitignoreContent[filePath as keyof typeof mockGitignoreContent] || '';
|
|
});
|
|
|
|
const result = await searchFiles('/mock/root', mockConfig);
|
|
expect(result).toEqual(['root/another/file3.js', 'root/subdir/file2.js', 'root/file1.js']);
|
|
expect(result).not.toContain('root/subdir/ignored.js');
|
|
});
|
|
|
|
test('should not apply .gitignore when useGitignore is false', async () => {
|
|
const mockConfig = createMockConfig({
|
|
include: ['**/*.js'],
|
|
ignore: {
|
|
useGitignore: false,
|
|
useDefaultPatterns: false,
|
|
customPatterns: [],
|
|
},
|
|
});
|
|
|
|
const mockFileStructure = [
|
|
'root/file1.js',
|
|
'root/another/file3.js',
|
|
'root/subdir/file2.js',
|
|
'root/subdir/ignored.js',
|
|
];
|
|
|
|
vi.mocked(globby).mockResolvedValue(mockFileStructure);
|
|
|
|
const result = await searchFiles('/mock/root', mockConfig);
|
|
|
|
expect(result).toEqual(mockFileStructure);
|
|
expect(result).toContain('root/subdir/ignored.js');
|
|
});
|
|
});
|
|
});
|