Ver Fonte

@directory not respecting .rooIgnore Fix (#4075)

* Issue fixed.

* Update src/core/mentions/index.ts

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* Update index.ts

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
xyOz há 7 meses atrás
pai
commit
aa6265462e

+ 51 - 23
src/core/mentions/index.ts

@@ -17,6 +17,8 @@ import { UrlContentFetcher } from "../../services/browser/UrlContentFetcher"
 
 import { FileContextTracker } from "../context-tracking/FileContextTracker"
 
+import { RooIgnoreController } from "../ignore/RooIgnoreController"
+
 export async function openMention(mention?: string): Promise<void> {
 	if (!mention) {
 		return
@@ -50,6 +52,8 @@ export async function parseMentions(
 	cwd: string,
 	urlContentFetcher: UrlContentFetcher,
 	fileContextTracker?: FileContextTracker,
+	rooIgnoreController?: RooIgnoreController,
+	showRooIgnoredFiles: boolean = true,
 ): Promise<string> {
 	const mentions: Set<string> = new Set()
 	let parsedText = text.replace(mentionRegexGlobal, (match, mention) => {
@@ -102,12 +106,11 @@ export async function parseMentions(
 		} else if (mention.startsWith("/")) {
 			const mentionPath = mention.slice(1)
 			try {
-				const content = await getFileOrFolderContent(mentionPath, cwd)
+				const content = await getFileOrFolderContent(mentionPath, cwd, rooIgnoreController, showRooIgnoredFiles)
 				if (mention.endsWith("/")) {
 					parsedText += `\n\n<folder_content path="${mentionPath}">\n${content}\n</folder_content>`
 				} else {
 					parsedText += `\n\n<file_content path="${mentionPath}">\n${content}\n</file_content>`
-					// Track that this file was mentioned and its content was included
 					if (fileContextTracker) {
 						await fileContextTracker.trackFileContext(mentionPath, "file_mentioned")
 					}
@@ -161,8 +164,12 @@ export async function parseMentions(
 	return parsedText
 }
 
-async function getFileOrFolderContent(mentionPath: string, cwd: string): Promise<string> {
-	// Unescape spaces in the path before resolving it
+async function getFileOrFolderContent(
+	mentionPath: string,
+	cwd: string,
+	rooIgnoreController?: any,
+	showRooIgnoredFiles: boolean = true,
+): Promise<string> {
 	const unescapedPath = unescapeSpaces(mentionPath)
 	const absPath = path.resolve(cwd, unescapedPath)
 
@@ -170,6 +177,9 @@ async function getFileOrFolderContent(mentionPath: string, cwd: string): Promise
 		const stats = await fs.stat(absPath)
 
 		if (stats.isFile()) {
+			if (rooIgnoreController && !rooIgnoreController.validateAccess(absPath)) {
+				return `(File ${mentionPath} is ignored by .rooignore)`
+			}
 			try {
 				const content = await extractTextFromFile(absPath)
 				return content
@@ -180,33 +190,51 @@ async function getFileOrFolderContent(mentionPath: string, cwd: string): Promise
 			const entries = await fs.readdir(absPath, { withFileTypes: true })
 			let folderContent = ""
 			const fileContentPromises: Promise<string | undefined>[] = []
-			entries.forEach((entry, index) => {
+			const LOCK_SYMBOL = "🔒"
+
+			for (let index = 0; index < entries.length; index++) {
+				const entry = entries[index]
 				const isLast = index === entries.length - 1
 				const linePrefix = isLast ? "└── " : "├── "
+				const entryPath = path.join(absPath, entry.name)
+
+				let isIgnored = false
+				if (rooIgnoreController) {
+					isIgnored = !rooIgnoreController.validateAccess(entryPath)
+				}
+
+				if (isIgnored && !showRooIgnoredFiles) {
+					continue
+				}
+
+				const displayName = isIgnored ? `${LOCK_SYMBOL} ${entry.name}` : entry.name
+
 				if (entry.isFile()) {
-					folderContent += `${linePrefix}${entry.name}\n`
-					const filePath = path.join(mentionPath, entry.name)
-					const absoluteFilePath = path.resolve(absPath, entry.name)
-					fileContentPromises.push(
-						(async () => {
-							try {
-								const isBinary = await isBinaryFile(absoluteFilePath).catch(() => false)
-								if (isBinary) {
+					folderContent += `${linePrefix}${displayName}\n`
+					if (!isIgnored) {
+						const filePath = path.join(mentionPath, entry.name)
+						const absoluteFilePath = path.resolve(absPath, entry.name)
+						fileContentPromises.push(
+							(async () => {
+								try {
+									const isBinary = await isBinaryFile(absoluteFilePath).catch(() => false)
+									if (isBinary) {
+										return undefined
+									}
+									const content = await extractTextFromFile(absoluteFilePath)
+									return `<file_content path="${filePath.toPosix()}">\n${content}\n</file_content>`
+								} catch (error) {
 									return undefined
 								}
-								const content = await extractTextFromFile(absoluteFilePath)
-								return `<file_content path="${filePath.toPosix()}">\n${content}\n</file_content>`
-							} catch (error) {
-								return undefined
-							}
-						})(),
-					)
+							})(),
+						)
+					}
 				} else if (entry.isDirectory()) {
-					folderContent += `${linePrefix}${entry.name}/\n`
+					folderContent += `${linePrefix}${displayName}/\n`
 				} else {
-					folderContent += `${linePrefix}${entry.name}\n`
+					folderContent += `${linePrefix}${displayName}\n`
 				}
-			})
+			}
 			const fileContents = (await Promise.all(fileContentPromises)).filter((content) => content)
 			return `${folderContent}\n${fileContents.join("\n\n")}`.trim()
 		} else {

+ 22 - 2
src/core/mentions/processUserContentMentions.ts

@@ -11,11 +11,15 @@ export async function processUserContentMentions({
 	cwd,
 	urlContentFetcher,
 	fileContextTracker,
+	rooIgnoreController,
+	showRooIgnoredFiles = true,
 }: {
 	userContent: Anthropic.Messages.ContentBlockParam[]
 	cwd: string
 	urlContentFetcher: UrlContentFetcher
 	fileContextTracker: FileContextTracker
+	rooIgnoreController?: any
+	showRooIgnoredFiles?: boolean
 }) {
 	// Process userContent array, which contains various block types:
 	// TextBlockParam, ImageBlockParam, ToolUseBlockParam, and ToolResultBlockParam.
@@ -35,7 +39,14 @@ export async function processUserContentMentions({
 				if (shouldProcessMentions(block.text)) {
 					return {
 						...block,
-						text: await parseMentions(block.text, cwd, urlContentFetcher, fileContextTracker),
+						text: await parseMentions(
+							block.text,
+							cwd,
+							urlContentFetcher,
+							fileContextTracker,
+							rooIgnoreController,
+							showRooIgnoredFiles,
+						),
 					}
 				}
 
@@ -45,7 +56,14 @@ export async function processUserContentMentions({
 					if (shouldProcessMentions(block.content)) {
 						return {
 							...block,
-							content: await parseMentions(block.content, cwd, urlContentFetcher, fileContextTracker),
+							content: await parseMentions(
+								block.content,
+								cwd,
+								urlContentFetcher,
+								fileContextTracker,
+								rooIgnoreController,
+								showRooIgnoredFiles,
+							),
 						}
 					}
 
@@ -61,6 +79,8 @@ export async function processUserContentMentions({
 										cwd,
 										urlContentFetcher,
 										fileContextTracker,
+										rooIgnoreController,
+										showRooIgnoredFiles,
 									),
 								}
 							}

+ 4 - 0
src/core/task/Task.ts

@@ -1107,11 +1107,15 @@ export class Task extends EventEmitter<ClineEvents> {
 			}),
 		)
 
+		const { showRooIgnoredFiles = true } = (await this.providerRef.deref()?.getState()) ?? {}
+
 		const parsedUserContent = await processUserContentMentions({
 			userContent,
 			cwd: this.cwd,
 			urlContentFetcher: this.urlContentFetcher,
 			fileContextTracker: this.fileContextTracker,
+			rooIgnoreController: this.rooIgnoreController,
+			showRooIgnoredFiles,
 		})
 
 		const environmentDetails = await getEnvironmentDetails(this, includeFileDetails)