11import fs from "node:fs/promises" ;
22import path from "node:path" ;
33
4+ export interface FileEntry {
5+ filePath : string ;
6+ content : string ;
7+ }
8+
49/**
510 * Checks whether the given file contains Git merge conflict markers.
611 *
7- * @param filePath - Absolute path to the file .
12+ * @param content - File content to check .
813 * @returns `true` if conflict markers exist, otherwise `false`.
914 */
10- const hasConflict = async ( filePath : string ) : Promise < boolean > => {
11- try {
12- const content = await fs . readFile ( filePath , "utf8" ) ;
13- return (
14- content . includes ( "<<<<<<<" ) && content . includes ( "=======" ) && content . includes ( ">>>>>>>" )
15- ) ;
16- } catch {
17- /* v8 ignore next 2 - If file cannot be read (permissions, etc.), treat as non-conflicted */
18- return false ;
19- }
15+ const hasConflict = ( content : string ) : boolean => {
16+ return content . includes ( "<<<<<<<" ) && content . includes ( "=======" ) && content . includes ( ">>>>>>>" ) ;
2017} ;
2118
2219export interface CollectFilesOptions {
@@ -37,16 +34,15 @@ export interface CollectFilesOptions {
3734 * Recursively collects files that match the provided `fileFilter`.
3835 *
3936 * - By default, only conflicted files are returned.
40- * - If `includeNonConflicted` is enabled, matching files are always included
41- * (conflict check is skipped).
37+ * - If `includeNonConflicted` is enabled, matching files are always included.
4238 *
4339 * @param options - Collection options, including `fileFilter` and traversal root.
44- * @returns A promise that resolves with an array of matching file paths .
40+ * @returns A promise that resolves with an array of `{ filePath, content }` .
4541 */
46- export const collectFiles = async ( options : CollectFilesOptions ) : Promise < string [ ] > => {
42+ export const collectFiles = async ( options : CollectFilesOptions ) : Promise < FileEntry [ ] > => {
4743 const { root = process . cwd ( ) , fileFilter, includeNonConflicted = false } = options ;
4844
49- const allFiles : string [ ] = [ ] ;
45+ const collected : FileEntry [ ] = [ ] ;
5046
5147 /**
5248 * Recursively traverses a directory, checking each file against
@@ -64,17 +60,21 @@ export const collectFiles = async (options: CollectFilesOptions): Promise<string
6460 /* v8 ignore next */
6561 await walk ( fullPath ) ;
6662 } else if ( fileFilter ( fullPath ) ) {
67- if ( includeNonConflicted ) {
68- allFiles . push ( fullPath ) ;
69- } else if ( await hasConflict ( fullPath ) ) {
70- allFiles . push ( fullPath ) ;
71- } else {
72- console . info ( `Skipped (no conflicts): ${ fullPath } ` ) ;
63+ try {
64+ const content = await fs . readFile ( fullPath , "utf8" ) ;
65+
66+ if ( includeNonConflicted || hasConflict ( content ) ) {
67+ collected . push ( { filePath : fullPath , content } ) ;
68+ } else {
69+ console . info ( `Skipped (no conflicts): ${ fullPath } ` ) ;
70+ }
71+ } catch {
72+ console . warn ( `Skipped (unreadable): ${ fullPath } ` ) ;
7373 }
7474 }
7575 }
7676 } ;
7777
7878 await walk ( root ) ;
79- return allFiles ;
79+ return collected ;
8080} ;
0 commit comments