Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 19 additions & 16 deletions src/core/output/outputGenerate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { XMLBuilder } from 'fast-xml-parser';
import Handlebars from 'handlebars';
import type { RepomixConfigMerged } from '../../config/configSchema.js';
import { RepomixError } from '../../shared/errorHandle.js';
import { type FileSearchResult, listDirectories, listFiles, searchFiles } from '../file/fileSearch.js';
import { listDirectories, listFiles, searchFiles } from '../file/fileSearch.js';
import { type FilesByRoot, generateTreeString, generateTreeStringWithRoots } from '../file/fileTreeGenerate.js';
import type { ProcessedFile } from '../file/fileTypes.js';
import type { GitDiffResult } from '../git/gitDiffHandle.js';
Expand Down Expand Up @@ -258,6 +258,7 @@ export const generateOutput = async (
gitDiffResult: GitDiffResult | undefined = undefined,
gitLogResult: GitLogResult | undefined = undefined,
filePathsByRoot?: FilesByRoot[],
emptyDirPaths?: string[],
deps = {
buildOutputGeneratorContext,
generateHandlebarOutput,
Expand All @@ -277,6 +278,7 @@ export const generateOutput = async (
gitDiffResult,
gitLogResult,
filePathsByRoot,
emptyDirPaths,
);
const renderContext = createRenderContext(outputGeneratorContext);

Expand All @@ -303,6 +305,7 @@ export const buildOutputGeneratorContext = async (
gitDiffResult: GitDiffResult | undefined = undefined,
gitLogResult: GitLogResult | undefined = undefined,
filePathsByRoot?: FilesByRoot[],
emptyDirPaths?: string[],
deps = {
listDirectories,
listFiles,
Expand Down Expand Up @@ -356,21 +359,21 @@ export const buildOutputGeneratorContext = async (
}
} else if (config.output.directoryStructure && config.output.includeEmptyDirectories) {
// Default behavior: include empty directories only
try {
const merged = (await Promise.all(rootDirs.map((rootDir) => deps.searchFiles(rootDir, config)))).reduce(
(acc: FileSearchResult, curr: FileSearchResult) =>
({
filePaths: [...acc.filePaths, ...curr.filePaths],
emptyDirPaths: [...acc.emptyDirPaths, ...curr.emptyDirPaths],
}) as FileSearchResult,
{ filePaths: [], emptyDirPaths: [] },
).emptyDirPaths;
directoryPathsForTree = [...new Set(merged)].sort();
} catch (error) {
throw new RepomixError(
`Failed to search for empty directories: ${error instanceof Error ? error.message : String(error)}`,
error instanceof Error ? { cause: error } : undefined,
);
if (emptyDirPaths) {
// Use pre-computed empty directory paths from the initial searchFiles call
directoryPathsForTree = emptyDirPaths;
} else {
// Fallback: if emptyDirPaths not provided (e.g., direct callers like packSkill)
try {
const searchResults = await Promise.all(rootDirs.map((rootDir) => deps.searchFiles(rootDir, config)));
const allEmptyDirs = searchResults.flatMap((result) => result.emptyDirPaths);
directoryPathsForTree = [...new Set(allEmptyDirs)].sort();
} catch (error) {
throw new RepomixError(
`Failed to search for empty directories: ${error instanceof Error ? error.message : String(error)}`,
error instanceof Error ? { cause: error } : undefined,
);
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/core/output/outputSplit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ const renderGroups = async (
gitDiffResult: GitDiffResult | undefined,
gitLogResult: GitLogResult | undefined,
filePathsByRoot: FilesByRoot[] | undefined,
emptyDirPaths: string[] | undefined,
generateOutput: GenerateOutputFn,
): Promise<string> => {
const chunkProcessedFiles = groupsToRender.flatMap((g) => g.processedFiles);
Expand All @@ -115,6 +116,7 @@ const renderGroups = async (
partIndex === 1 ? gitDiffResult : undefined,
partIndex === 1 ? gitLogResult : undefined,
filePathsByRoot,
emptyDirPaths,
);
};

Expand All @@ -128,6 +130,7 @@ export const generateSplitOutputParts = async ({
gitLogResult,
progressCallback,
filePathsByRoot,
emptyDirPaths,
deps,
}: {
rootDirs: string[];
Expand All @@ -139,6 +142,7 @@ export const generateSplitOutputParts = async ({
gitLogResult: GitLogResult | undefined;
progressCallback: RepomixProgressCallback;
filePathsByRoot?: FilesByRoot[];
emptyDirPaths?: string[];
deps: {
generateOutput: GenerateOutputFn;
};
Expand Down Expand Up @@ -178,6 +182,7 @@ export const generateSplitOutputParts = async ({
gitDiffResult,
gitLogResult,
filePathsByRoot,
emptyDirPaths,
deps.generateOutput,
);
const nextBytes = getUtf8ByteLength(nextContent);
Expand Down Expand Up @@ -215,6 +220,7 @@ export const generateSplitOutputParts = async ({
gitDiffResult,
gitLogResult,
filePathsByRoot,
emptyDirPaths,
deps.generateOutput,
);
const singleGroupBytes = getUtf8ByteLength(singleGroupContent);
Expand Down
14 changes: 9 additions & 5 deletions src/core/packager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,18 @@ export const pack = async (
logMemoryUsage('Pack - Start');

progressCallback('Searching for files...');
const filePathsByDir = await withMemoryLogging('Search Files', async () =>
const searchResultsByDir = await withMemoryLogging('Search Files', async () =>
Promise.all(
rootDirs.map(async (rootDir) => ({
rootDir,
filePaths: (await deps.searchFiles(rootDir, config, explicitFiles)).filePaths,
})),
rootDirs.map(async (rootDir) => {
const result = await deps.searchFiles(rootDir, config, explicitFiles);
return { rootDir, ...result };
}),
),
);

const filePathsByDir = searchResultsByDir.map(({ rootDir, filePaths }) => ({ rootDir, filePaths }));
const allEmptyDirPaths = [...new Set(searchResultsByDir.flatMap(({ emptyDirPaths }) => emptyDirPaths))].sort();

// Sort file paths
progressCallback('Sorting files...');
const allFilePaths = filePathsByDir.flatMap(({ filePaths }) => filePaths);
Expand Down Expand Up @@ -167,6 +170,7 @@ export const pack = async (
gitLogResult,
progressCallback,
filePathsByRoot,
allEmptyDirPaths,
);

const metrics = await withMemoryLogging('Calculate Metrics', () =>
Expand Down
17 changes: 16 additions & 1 deletion src/core/packager/produceOutput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const produceOutput = async (
gitLogResult: GitLogResult | undefined,
progressCallback: RepomixProgressCallback,
filePathsByRoot?: FilesByRoot[],
emptyDirPaths?: string[],
overrideDeps: Partial<typeof defaultDeps> = {},
): Promise<ProduceOutputResult> => {
const deps = { ...defaultDeps, ...overrideDeps };
Expand All @@ -47,6 +48,7 @@ export const produceOutput = async (
gitLogResult,
progressCallback,
filePathsByRoot,
emptyDirPaths,
deps,
);
}
Expand All @@ -60,6 +62,7 @@ export const produceOutput = async (
gitLogResult,
progressCallback,
filePathsByRoot,
emptyDirPaths,
deps,
);
};
Expand All @@ -74,6 +77,7 @@ const generateAndWriteSplitOutput = async (
gitLogResult: GitLogResult | undefined,
progressCallback: RepomixProgressCallback,
filePathsByRoot: FilesByRoot[] | undefined,
emptyDirPaths: string[] | undefined,
deps: typeof defaultDeps,
): Promise<ProduceOutputResult> => {
const parts = await withMemoryLogging('Generate Split Output', async () => {
Expand All @@ -87,6 +91,7 @@ const generateAndWriteSplitOutput = async (
gitLogResult,
progressCallback,
filePathsByRoot,
emptyDirPaths,
deps: {
generateOutput: deps.generateOutput,
},
Expand Down Expand Up @@ -124,10 +129,20 @@ const generateAndWriteSingleOutput = async (
gitLogResult: GitLogResult | undefined,
progressCallback: RepomixProgressCallback,
filePathsByRoot: FilesByRoot[] | undefined,
emptyDirPaths: string[] | undefined,
deps: typeof defaultDeps,
): Promise<ProduceOutputResult> => {
const output = await withMemoryLogging('Generate Output', () =>
deps.generateOutput(rootDirs, config, processedFiles, allFilePaths, gitDiffResult, gitLogResult, filePathsByRoot),
deps.generateOutput(
rootDirs,
config,
processedFiles,
allFilePaths,
gitDiffResult,
gitLogResult,
filePathsByRoot,
emptyDirPaths,
),
);

progressCallback('Writing output file...');
Expand Down
2 changes: 2 additions & 0 deletions tests/core/output/diffsInOutput.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ index 123..456 100644
gitDiffResult,
undefined,
undefined,
undefined,
{
buildOutputGeneratorContext: mockBuildOutputGeneratorContext,
generateHandlebarOutput: mockGenerateHandlebarOutput,
Expand Down Expand Up @@ -204,6 +205,7 @@ index 123..456 100644
gitDiffResult,
undefined,
undefined,
undefined,
{
buildOutputGeneratorContext: mockBuildOutputGeneratorContext,
generateHandlebarOutput: mockGenerateHandlebarOutput,
Expand Down
2 changes: 2 additions & 0 deletions tests/core/output/flagFullDirectoryStructure.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ describe('includeFullDirectoryStructure flag', () => {
undefined,
undefined,
undefined,
undefined,
deps,
);

Expand Down Expand Up @@ -105,6 +106,7 @@ describe('includeFullDirectoryStructure flag', () => {
undefined,
undefined,
undefined,
undefined,
deps,
);

Expand Down
2 changes: 2 additions & 0 deletions tests/core/output/outputGenerate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ describe('outputGenerate', () => {
undefined,
undefined,
undefined,
undefined,
mockDeps,
);

Expand All @@ -61,6 +62,7 @@ describe('outputGenerate', () => {
undefined,
undefined,
undefined,
undefined,
);
expect(output).toBe('mock output');
});
Expand Down
5 changes: 5 additions & 0 deletions tests/core/output/outputGenerateDiffs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ describe('Output Generation with Diffs', () => {
gitDiffResult,
undefined,
undefined,
undefined,
mockDeps,
);

Expand Down Expand Up @@ -123,6 +124,7 @@ describe('Output Generation with Diffs', () => {
undefined,
undefined,
undefined,
undefined,
mockDeps,
);

Expand Down Expand Up @@ -158,6 +160,7 @@ describe('Output Generation with Diffs', () => {
undefined,
undefined,
undefined,
undefined,
mockDeps,
);

Expand Down Expand Up @@ -193,6 +196,7 @@ describe('Output Generation with Diffs', () => {
undefined,
undefined,
undefined,
undefined,
mockDeps,
);

Expand Down Expand Up @@ -238,6 +242,7 @@ describe('Output Generation with Diffs', () => {
undefined,
undefined,
undefined,
undefined,
mockDeps,
);

Expand Down
1 change: 1 addition & 0 deletions tests/core/packager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ describe('packager', () => {
undefined,
progressCallback,
[{ rootLabel: 'root', files: mockFilePaths }],
[],
);
expect(mockDeps.calculateMetrics).toHaveBeenCalledWith(
mockProcessedFiles,
Expand Down
33 changes: 30 additions & 3 deletions tests/core/packager/produceOutput.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ describe('produceOutput', () => {
undefined,
progressCallback,
undefined,
undefined,
mockDeps,
);

Expand All @@ -37,6 +38,7 @@ describe('produceOutput', () => {
undefined,
undefined,
undefined,
undefined,
);
expect(mockDeps.writeOutputToDisk).toHaveBeenCalledWith('generated output', mockConfig);
expect(mockDeps.copyToClipboardIfEnabled).toHaveBeenCalledWith('generated output', progressCallback, mockConfig);
Expand All @@ -61,6 +63,7 @@ describe('produceOutput', () => {
gitLogResult as Parameters<typeof produceOutput>[5],
vi.fn(),
undefined,
undefined,
mockDeps,
);

Expand All @@ -72,6 +75,7 @@ describe('produceOutput', () => {
gitDiffResult,
gitLogResult,
undefined,
undefined,
);
});

Expand All @@ -80,7 +84,18 @@ describe('produceOutput', () => {
const mockConfig = createMockConfig();
const progressCallback = vi.fn();

await produceOutput(['/root'], mockConfig, [], [], undefined, undefined, progressCallback, undefined, mockDeps);
await produceOutput(
['/root'],
mockConfig,
[],
[],
undefined,
undefined,
progressCallback,
undefined,
undefined,
mockDeps,
);

expect(progressCallback).toHaveBeenCalledWith('Writing output file...');
});
Expand Down Expand Up @@ -116,6 +131,7 @@ describe('produceOutput', () => {
undefined,
progressCallback,
undefined,
undefined,
mockDeps,
);

Expand All @@ -134,7 +150,18 @@ describe('produceOutput', () => {
});
const progressCallback = vi.fn();

await produceOutput(['/root'], mockConfig, [], [], undefined, undefined, progressCallback, undefined, mockDeps);
await produceOutput(
['/root'],
mockConfig,
[],
[],
undefined,
undefined,
progressCallback,
undefined,
undefined,
mockDeps,
);

expect(progressCallback).toHaveBeenCalledWith('Writing output files...');
});
Expand All @@ -148,7 +175,7 @@ describe('produceOutput', () => {
},
});

await produceOutput(['/root'], mockConfig, [], [], undefined, undefined, vi.fn(), undefined, mockDeps);
await produceOutput(['/root'], mockConfig, [], [], undefined, undefined, vi.fn(), undefined, undefined, mockDeps);

expect(mockDeps.copyToClipboardIfEnabled).not.toHaveBeenCalled();
});
Expand Down
Loading
Loading