|
1 | 1 | import { Subscription } from 'rxjs' |
2 | | -import * as sourcegraph from 'sourcegraph' |
| 2 | +import sourcegraph from 'sourcegraph' |
3 | 3 | import { evaluateAndCreateCampaignSpec } from '@sourcegraph/campaigns-client' |
4 | 4 | import slugify from 'slugify' |
5 | 5 | import { getCurrentUser } from './util' |
| 6 | +import { editFile } from './edit-file' |
6 | 7 |
|
7 | 8 | // TODO: sanitize this for real, it gets used in the description of the campaign |
8 | 9 | const escapedMarkdownCode = (text: string): string => '`' + text.replace(/`/g, '\\`') + '`' |
9 | 10 |
|
10 | | -// TODO: instead of using fileFilter, use the search results as the list of matching files |
11 | | -const fileFilter = (path: string): boolean => path.endsWith('.yaml') || path.endsWith('.yml') || path.endsWith('.md') |
12 | | - |
13 | 11 | export const registerFindReplaceAction = (): Subscription => { |
14 | 12 | const subscription = new Subscription() |
15 | 13 | subscription.add( |
16 | | - sourcegraph.commands.registerCommand('start-find-replace', async (searchQuery: string) => { |
| 14 | + sourcegraph.commands.registerCommand('findReplace.startFindReplace', async (searchQuery: string) => { |
17 | 15 | // TODO: in the future, use the search query to get the list of matching files. |
18 | 16 | console.log('context.searchQuery', searchQuery) |
19 | 17 |
|
| 18 | + if (!searchQuery) { |
| 19 | + return |
| 20 | + } |
| 21 | + |
20 | 22 | // To create campaigns, a namespace is used, which can be the current user's username. |
21 | 23 | const currentUser = await getCurrentUser() |
22 | | - const namespaceName = currentUser?.username |
23 | | - console.log('currentUser', currentUser) |
| 24 | + if (!currentUser) { |
| 25 | + throw new Error('No current user') |
| 26 | + } |
| 27 | + const namespaceName = currentUser.username |
24 | 28 |
|
25 | | - const match = await sourcegraph.app.activeWindow!.showInputBox({ |
| 29 | + const findString = await sourcegraph.app.activeWindow!.showInputBox({ |
26 | 30 | prompt: 'Find all matches of:', |
27 | 31 | }) |
28 | | - if (!match) { |
| 32 | + if (!findString) { |
29 | 33 | return |
30 | 34 | } |
31 | 35 |
|
32 | | - const replacement = await sourcegraph.app.activeWindow!.showInputBox({ |
| 36 | + const replacementString = await sourcegraph.app.activeWindow!.showInputBox({ |
33 | 37 | prompt: 'Replace with:', |
34 | 38 | }) |
35 | 39 | // Empty string is a valid replacement, so compare directly with undefined. |
36 | | - if (replacement === undefined) { |
| 40 | + if (replacementString === undefined) { |
37 | 41 | return |
38 | 42 | } |
39 | 43 |
|
40 | | - const name = `replace-${slugify(match)}-with-${slugify(replacement)}` |
41 | | - const description = `Replace ${escapedMarkdownCode(match)} with ${escapedMarkdownCode(replacement)}` |
| 44 | + const campaignName = `replace-${slugify(findString)}-with-${slugify(replacementString)}` |
| 45 | + const description = `Replace ${escapedMarkdownCode(findString)} with ${escapedMarkdownCode( |
| 46 | + replacementString |
| 47 | + )}` |
42 | 48 |
|
43 | 49 | let percentage = 0 |
44 | 50 | const { applyURL, diffStat } = await sourcegraph.app.activeWindow!.withProgress( |
45 | 51 | { title: '**Find-replace**' }, |
46 | | - async reporter => |
| 52 | + reporter => |
47 | 53 | evaluateAndCreateCampaignSpec(namespaceName, { |
48 | | - name, |
| 54 | + name: campaignName, |
49 | 55 | on: [ |
50 | 56 | { |
51 | | - repositoriesMatchingQuery: match, |
| 57 | + repositoriesMatchingQuery: searchQuery, |
52 | 58 | }, |
53 | 59 | ], |
54 | 60 | description, |
55 | 61 | steps: [ |
56 | 62 | { |
57 | | - fileFilter, |
| 63 | + fileFilter: () => true, |
58 | 64 | editFile: (path, text) => { |
59 | | - if (!text.includes(match)) { |
| 65 | + if (!text.includes(findString)) { |
| 66 | + // skip the file by returning null |
60 | 67 | return null |
61 | 68 | } |
62 | 69 |
|
63 | 70 | percentage += (100 - percentage) / 100 |
64 | 71 | reporter.next({ message: `Computing changes in ${path}`, percentage }) |
65 | | - return text.split(match).join(replacement) |
| 72 | + |
| 73 | + return editFile(text, findString, replacementString) |
66 | 74 | }, |
67 | 75 | }, |
68 | 76 | ], |
69 | 77 | changesetTemplate: { |
70 | 78 | title: description, |
71 | | - branch: `campaign/${name}`, |
| 79 | + branch: `campaign/${campaignName}`, |
72 | 80 | commit: { |
73 | 81 | message: description, |
74 | 82 | author: { |
|
0 commit comments