Skip to content

Commit dee210b

Browse files
committed
Prevent concurrent file search operations by adding a search in progress lock
- make sure 'search' cant be opened again while Intelligent/Agentic search is ongoing └── apps └── editor └── src ├── commands │ ├── apply-response-command │ │ └── apply-response-command.ts │ ├── history-command │ │ └── history-command.ts │ └── search-files-commands │ ├── index.ts │ ├── search-files-commands.ts │ └── utils │ ├── get-target-folder-path.ts │ └── prompt-for-provided-results.ts ├── features │ └── search-files │ ├── index.ts │ ├── search-files.ts │ ├── search-modes │ │ ├── perform-agent-search-mode │ │ │ ├── agents │ │ │ │ ├── antigravity.ts │ │ │ │ ├── claude.ts │ │ │ │ ├── codex.ts │ │ │ │ ├── cursor.ts │ │ │ │ ├── grok.ts │ │ │ │ ├── muse.ts │ │ │ │ └── opencode.ts │ │ │ ├── index.ts │ │ │ ├── perform-agent-search-mode.ts │ │ │ ├── types.ts │ │ │ └── utils.ts │ │ ├── perform-intelligent-search-mode.ts │ │ ├── perform-keywords-search-mode.ts │ │ └── perform-phrase-search-mode.ts │ └── utils │ ├── analyze-files.ts │ ├── check-matches-condition.ts │ ├── create-search-regex.ts │ ├── group-quick-pick-items.ts │ ├── handle-parent-folder-result.ts │ ├── map-files-to-quick-pick-items.ts │ ├── prompt-for-config.ts │ ├── prompt-for-intelligent-search-results.ts │ ├── prompt-for-keywords-match-mode.ts │ ├── prompt-for-keywords-target.ts │ ├── prompt-for-search-mode.ts │ ├── prompt-for-search-results.ts │ ├── prompt-for-search-term.ts │ ├── prompt-for-shrink-mode.ts │ ├── search-files-by-intelligent.ts │ ├── search-files-by-keywords.ts │ ├── search-files-by-phrase.ts │ └── show-search-results-quick-pick.ts └── i18n └── translations ├── commands │ └── search-files.ts └── features └── search-files.ts
1 parent 2f983a1 commit dee210b

2 files changed

Lines changed: 176 additions & 130 deletions

File tree

‎apps/editor/src/commands/search-files-commands/search-files-commands.ts‎

Lines changed: 158 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import { WebSocketManager } from '@/services/websocket-manager'
88
import { prompt_for_provided_results } from './utils/prompt-for-provided-results'
99
import { get_target_folder_path } from './utils/get-target-folder-path'
1010

11+
let search_in_progress = false
12+
1113
export const search_files_commands = (
1214
workspace_provider: WorkspaceProvider,
1315
extension_context: vscode.ExtensionContext,
@@ -114,177 +116,203 @@ export const search_files_commands = (
114116
is_workspace_action?: boolean
115117
}
116118
) => {
117-
if (options?.provided_files) {
118-
let resolved_all_files: string[] = []
119-
120-
if (options.is_search_in_selected) {
121-
const currently_checked = workspace_provider.get_checked_files()
122-
if (options.folder_path) {
123-
resolved_all_files = currently_checked.filter((f) => {
124-
const relative = path.relative(options.folder_path!, f)
125-
return !relative.startsWith('..') && !path.isAbsolute(relative)
126-
})
127-
} else {
128-
resolved_all_files = currently_checked
129-
}
130-
} else {
131-
if (options.folder_path) {
132-
resolved_all_files = await workspace_provider.find_all_files(
133-
options.folder_path
134-
)
119+
if (search_in_progress) {
120+
vscode.window.showWarningMessage(
121+
t('feature.search-files.warning.search-in-progress' as any)
122+
)
123+
return
124+
}
125+
search_in_progress = true
126+
try {
127+
if (options?.provided_files) {
128+
let resolved_all_files: string[] = []
129+
130+
if (options.is_search_in_selected) {
131+
const currently_checked = workspace_provider.get_checked_files()
132+
if (options.folder_path) {
133+
resolved_all_files = currently_checked.filter((f) => {
134+
const relative = path.relative(options.folder_path!, f)
135+
return !relative.startsWith('..') && !path.isAbsolute(relative)
136+
})
137+
} else {
138+
resolved_all_files = currently_checked
139+
}
135140
} else {
136-
const roots = workspace_provider.get_workspace_roots()
137-
for (const root of roots) {
138-
const result = await workspace_provider.find_all_files(root)
139-
resolved_all_files.push(...result)
141+
if (options.folder_path) {
142+
resolved_all_files = await workspace_provider.find_all_files(
143+
options.folder_path
144+
)
145+
} else {
146+
const roots = workspace_provider.get_workspace_roots()
147+
for (const root of roots) {
148+
const result = await workspace_provider.find_all_files(root)
149+
resolved_all_files.push(...result)
150+
}
140151
}
141152
}
142-
}
143-
144-
let decision:
145-
| { selected_paths: string[]; matched_paths: string[]; title?: string }
146-
| undefined = undefined
147153

148-
let restored_selected_paths: string[] | undefined = undefined
149-
let restored_unmatched_paths: string[] | undefined = undefined
150-
151-
while (true) {
152-
const result = await prompt_for_provided_results({
153-
files: options.provided_files,
154-
workspace_provider,
155-
restored_selected_paths,
156-
restored_unmatched_paths,
157-
is_search_in_selected: options.is_search_in_selected,
158-
searched_files: resolved_all_files
159-
})
154+
let decision:
155+
| {
156+
selected_paths: string[]
157+
matched_paths: string[]
158+
title?: string
159+
}
160+
| undefined = undefined
160161

161-
if (!result) return
162+
let restored_selected_paths: string[] | undefined = undefined
163+
let restored_unmatched_paths: string[] | undefined = undefined
162164

163-
if ('action' in result) {
164-
const sub_search_result = await search_files({
165-
get_files: async () => result.matched_paths,
165+
while (true) {
166+
const result = await prompt_for_provided_results({
167+
files: options.provided_files,
166168
workspace_provider,
167-
extension_context,
168-
websocket_manager,
169-
show_back_button: true,
170-
is_sub_search: true
169+
restored_selected_paths,
170+
restored_unmatched_paths,
171+
is_search_in_selected: options.is_search_in_selected,
172+
searched_files: resolved_all_files
171173
})
172174

173-
if (sub_search_result === 'back') {
174-
restored_selected_paths = result.selected_paths
175-
restored_unmatched_paths = result.unmatched_paths
176-
continue
177-
}
175+
if (!result) return
178176

179-
if (!sub_search_result) return
177+
if ('action' in result) {
178+
const sub_search_result = await search_files({
179+
get_files: async () => result.matched_paths,
180+
workspace_provider,
181+
extension_context,
182+
websocket_manager,
183+
show_back_button: true,
184+
is_sub_search: true
185+
})
186+
187+
if (sub_search_result === 'back') {
188+
restored_selected_paths = result.selected_paths
189+
restored_unmatched_paths = result.unmatched_paths
190+
continue
191+
}
192+
193+
if (!sub_search_result) return
194+
195+
decision = sub_search_result
196+
break
197+
}
180198

181-
decision = sub_search_result
199+
decision = result
182200
break
183201
}
184202

185-
decision = result
186-
break
203+
await process_search_result({
204+
result: decision,
205+
resolved_all_files,
206+
is_provided_files: true,
207+
is_search_in_selected: options.is_search_in_selected,
208+
folder_path: options.folder_path
209+
})
210+
return
187211
}
188212

189-
await process_search_result({
190-
result: decision,
191-
resolved_all_files,
192-
is_provided_files: true,
193-
is_search_in_selected: options.is_search_in_selected,
194-
folder_path: options.folder_path
195-
})
196-
return
197-
}
213+
const folder_path = await get_target_folder_path(item)
198214

199-
const folder_path = await get_target_folder_path(item)
215+
let all_files: string[] | undefined
200216

201-
let all_files: string[] | undefined
202-
203-
const get_files_lazy = async () => {
204-
if (all_files) return all_files
205-
const files: string[] = []
206-
if (folder_path) {
207-
const result = await workspace_provider.find_all_files(folder_path)
208-
files.push(...result)
209-
} else {
210-
const roots = workspace_provider.get_workspace_roots()
211-
for (const root of roots) {
212-
const result = await workspace_provider.find_all_files(root)
217+
const get_files_lazy = async () => {
218+
if (all_files) return all_files
219+
const files: string[] = []
220+
if (folder_path) {
221+
const result = await workspace_provider.find_all_files(folder_path)
213222
files.push(...result)
223+
} else {
224+
const roots = workspace_provider.get_workspace_roots()
225+
for (const root of roots) {
226+
const result = await workspace_provider.find_all_files(root)
227+
files.push(...result)
228+
}
214229
}
230+
all_files = files
231+
return all_files
215232
}
216-
all_files = files
217-
return all_files
218-
}
219233

220-
while (true) {
221-
const result = await search_files({
222-
get_files: get_files_lazy,
223-
workspace_provider,
224-
extension_context,
225-
websocket_manager,
226-
folder_path,
227-
is_workspace_action: options?.is_workspace_action
228-
})
234+
while (true) {
235+
const result = await search_files({
236+
get_files: get_files_lazy,
237+
workspace_provider,
238+
extension_context,
239+
websocket_manager,
240+
folder_path,
241+
is_workspace_action: options?.is_workspace_action
242+
})
229243

230-
if (!result || result == 'back') return
244+
if (!result || result == 'back') return
231245

232-
const resolved_all_files = await get_files_lazy()
246+
const resolved_all_files = await get_files_lazy()
233247

234-
await process_search_result({
235-
result,
236-
resolved_all_files,
237-
folder_path
238-
})
248+
await process_search_result({
249+
result,
250+
resolved_all_files,
251+
folder_path
252+
})
239253

240-
break
254+
break
255+
}
256+
} finally {
257+
search_in_progress = false
241258
}
242259
}
243260

244261
const search_selected_files_handler = async (item?: any) => {
245-
const currently_checked = workspace_provider.get_checked_files()
246-
if (currently_checked.length === 0) {
262+
if (search_in_progress) {
263+
vscode.window.showWarningMessage(
264+
t('feature.search-files.warning.search-in-progress' as any)
265+
)
247266
return
248267
}
268+
search_in_progress = true
269+
try {
270+
const currently_checked = workspace_provider.get_checked_files()
271+
if (currently_checked.length === 0) {
272+
return
273+
}
249274

250-
const folder_path = await get_target_folder_path(item)
275+
const folder_path = await get_target_folder_path(item)
251276

252-
let files_to_search = currently_checked
253-
if (folder_path) {
254-
files_to_search = currently_checked.filter((f) => {
255-
const relative = path.relative(folder_path, f)
256-
return !relative.startsWith('..') && !path.isAbsolute(relative)
257-
})
258-
}
277+
let files_to_search = currently_checked
278+
if (folder_path) {
279+
files_to_search = currently_checked.filter((f) => {
280+
const relative = path.relative(folder_path, f)
281+
return !relative.startsWith('..') && !path.isAbsolute(relative)
282+
})
283+
}
259284

260-
if (files_to_search.length === 0) {
261-
return
262-
}
285+
if (files_to_search.length === 0) {
286+
return
287+
}
263288

264-
const get_files_lazy = async () => files_to_search
289+
const get_files_lazy = async () => files_to_search
265290

266-
while (true) {
267-
const result = await search_files({
268-
get_files: get_files_lazy,
269-
workspace_provider,
270-
extension_context,
271-
websocket_manager,
272-
is_search_in_selected: true,
273-
folder_path
274-
})
291+
while (true) {
292+
const result = await search_files({
293+
get_files: get_files_lazy,
294+
workspace_provider,
295+
extension_context,
296+
websocket_manager,
297+
is_search_in_selected: true,
298+
folder_path
299+
})
275300

276-
if (!result || result == 'back') return
301+
if (!result || result == 'back') return
277302

278-
const resolved_all_files = await get_files_lazy()
303+
const resolved_all_files = await get_files_lazy()
279304

280-
await process_search_result({
281-
result,
282-
resolved_all_files,
283-
folder_path,
284-
is_search_in_selected: true
285-
})
305+
await process_search_result({
306+
result,
307+
resolved_all_files,
308+
folder_path,
309+
is_search_in_selected: true
310+
})
286311

287-
break
312+
break
313+
}
314+
} finally {
315+
search_in_progress = false
288316
}
289317
}
290318

‎apps/editor/src/i18n/translations/features/search-files.ts‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,5 +1276,23 @@ export const translations = {
12761276
cs: 'čekání na agenta...',
12771277
hu: 'várakozás az ügynökre...',
12781278
bg: 'изчакване на агент...'
1279+
},
1280+
'feature.search-files.warning.search-in-progress': {
1281+
en: 'Search is already in progress.',
1282+
pl: 'Wyszukiwanie jest już w toku.',
1283+
'zh-cn': '搜索已在进行中。',
1284+
ja: '検索はすでに進行中です。',
1285+
'zh-tw': '搜尋已在進行中。',
1286+
de: 'Suche läuft bereits.',
1287+
es: 'La búsqueda ya está en curso.',
1288+
fr: 'La recherche est déjà en cours.',
1289+
'pt-br': 'A pesquisa já está em andamento.',
1290+
ru: 'Поиск уже выполняется.',
1291+
ko: '검색이 이미 진행 중입니다.',
1292+
it: 'La ricerca è già in corso.',
1293+
tr: 'Arama zaten devam ediyor.',
1294+
cs: 'Hledání již probíhá.',
1295+
hu: 'A keresés már folyamatban van.',
1296+
bg: 'Търсенето вече е в ход.'
12791297
}
12801298
} as const

0 commit comments

Comments
 (0)