Skip to content

Commit 807e9e2

Browse files
committed
refactor: do not export gitdiff
1 parent 787e1a6 commit 807e9e2

File tree

4 files changed

+180
-188
lines changed

4 files changed

+180
-188
lines changed

packages/core/src/amazonq/util/gitDiffUtils.ts

Lines changed: 0 additions & 179 deletions
This file was deleted.

packages/core/src/codewhisperer/util/zipUtil.ts

Lines changed: 174 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ import { FeatureUseCase } from '../models/constants'
2828
import { ProjectZipError } from '../../amazonqTest/error'
2929
import { normalize } from '../../shared/utilities/pathUtils'
3030
import { ZipStream } from '../../shared/utilities/zipStream'
31-
import { getTextContent } from '../../shared/utilities/vsCodeUtils'
32-
import { getGitDiffContent } from '../../amazonq/util/gitDiffUtils'
31+
import { getTextContent } from '../../shared/utilities/textDocumentUtilities'
32+
import { ChildProcess, ChildProcessOptions } from '../../shared/utilities/processUtils'
33+
import { removeAnsi } from '../../shared/utilities/textUtilities'
3334

3435
export interface ZipMetadata {
3536
rootDir: string
@@ -217,7 +218,7 @@ export class ZipUtil {
217218
filePath?: string,
218219
scope?: CodeWhispererConstants.CodeAnalysisScope
219220
) {
220-
const gitDiffContent = await getGitDiffContent(projectPaths, filePath)
221+
const gitDiffContent = await getGitDiffContentForProjects(projectPaths, filePath)
221222
if (gitDiffContent) {
222223
zip.writeString(gitDiffContent, ZipConstants.codeDiffFilePath)
223224
}
@@ -451,3 +452,173 @@ export class ZipUtil {
451452
logger.verbose(`Complete cleaning up temporary files.`)
452453
}
453454
}
455+
456+
// TODO: port this to its own utility with tests.
457+
interface GitDiffOptions {
458+
projectPath: string
459+
projectName: string
460+
filepath?: string
461+
scope?: CodeWhispererConstants.CodeAnalysisScope
462+
}
463+
464+
async function getGitDiffContentForProjects(
465+
projectPaths: string[],
466+
filepath?: string,
467+
scope?: CodeWhispererConstants.CodeAnalysisScope
468+
) {
469+
let gitDiffContent = ''
470+
for (const projectPath of projectPaths) {
471+
const projectName = path.basename(projectPath)
472+
gitDiffContent += await getGitDiffContent({
473+
projectPath,
474+
projectName,
475+
filepath,
476+
scope,
477+
})
478+
}
479+
return gitDiffContent
480+
}
481+
482+
async function getGitDiffContent(options: GitDiffOptions): Promise<string> {
483+
const { projectPath, projectName, filepath: filePath, scope } = options
484+
const isProjectScope = scope === CodeWhispererConstants.CodeAnalysisScope.PROJECT
485+
486+
const untrackedFilesString = await getGitUntrackedFiles(projectPath)
487+
const untrackedFilesArray = untrackedFilesString?.trim()?.split('\n')?.filter(Boolean)
488+
489+
if (isProjectScope && untrackedFilesArray && !untrackedFilesArray.length) {
490+
return await generateHeadDiff(projectPath, projectName)
491+
}
492+
493+
let diffContent = ''
494+
495+
if (isProjectScope) {
496+
diffContent = await generateHeadDiff(projectPath, projectName)
497+
498+
if (untrackedFilesArray) {
499+
const untrackedDiffs = await Promise.all(
500+
untrackedFilesArray.map((file) => generateNewFileDiff(projectPath, projectName, file))
501+
)
502+
diffContent += untrackedDiffs.join('')
503+
}
504+
} else if (!isProjectScope && filePath) {
505+
const relativeFilePath = path.relative(projectPath, filePath)
506+
507+
const newFileDiff = await generateNewFileDiff(projectPath, projectName, relativeFilePath)
508+
diffContent = rewriteDiff(newFileDiff)
509+
}
510+
return diffContent
511+
}
512+
513+
async function getGitUntrackedFiles(projectPath: string): Promise<string | undefined> {
514+
const checkNewFileArgs = ['ls-files', '--others', '--exclude-standard']
515+
const checkProcess = new ChildProcess('git', checkNewFileArgs)
516+
517+
try {
518+
let output = ''
519+
await checkProcess.run({
520+
rejectOnError: true,
521+
rejectOnErrorCode: true,
522+
onStdout: (text) => {
523+
output += text
524+
},
525+
spawnOptions: {
526+
cwd: projectPath,
527+
},
528+
})
529+
return output
530+
} catch (err) {
531+
getLogger().warn(`Failed to check if file is new: ${err}`)
532+
return undefined
533+
}
534+
}
535+
536+
async function generateHeadDiff(projectPath: string, projectName: string, relativePath?: string): Promise<string> {
537+
let diffContent = ''
538+
539+
const gitArgs = [
540+
'diff',
541+
'HEAD',
542+
`--src-prefix=a/${projectName}/`,
543+
`--dst-prefix=b/${projectName}/`,
544+
...(relativePath ? [relativePath] : []),
545+
]
546+
547+
const childProcess = new ChildProcess('git', gitArgs)
548+
549+
const runOptions: ChildProcessOptions = {
550+
rejectOnError: true,
551+
rejectOnErrorCode: true,
552+
onStdout: (text) => {
553+
diffContent += text
554+
getLogger().verbose(removeAnsi(text))
555+
},
556+
onStderr: (text) => {
557+
getLogger().error(removeAnsi(text))
558+
},
559+
spawnOptions: {
560+
cwd: projectPath,
561+
},
562+
}
563+
564+
try {
565+
await childProcess.run(runOptions)
566+
return diffContent
567+
} catch (err) {
568+
getLogger().warn(`Failed to run command \`${childProcess.toString()}\`: ${err}`)
569+
return ''
570+
}
571+
}
572+
573+
async function generateNewFileDiff(projectPath: string, projectName: string, relativePath: string): Promise<string> {
574+
let diffContent = ''
575+
576+
const gitArgs = [
577+
'diff',
578+
'--no-index',
579+
`--src-prefix=a/${projectName}/`,
580+
`--dst-prefix=b/${projectName}/`,
581+
'/dev/null', // Use /dev/null as the old file
582+
relativePath,
583+
]
584+
585+
const childProcess = new ChildProcess('git', gitArgs)
586+
const runOptions: ChildProcessOptions = {
587+
rejectOnError: false,
588+
rejectOnErrorCode: false,
589+
onStdout: (text) => {
590+
diffContent += text
591+
getLogger().verbose(removeAnsi(text))
592+
},
593+
onStderr: (text) => {
594+
getLogger().error(removeAnsi(text))
595+
},
596+
spawnOptions: {
597+
cwd: projectPath,
598+
},
599+
}
600+
601+
try {
602+
await childProcess.run(runOptions)
603+
return diffContent
604+
} catch (err) {
605+
getLogger().warn(`Failed to run diff command: ${err}`)
606+
return ''
607+
}
608+
}
609+
610+
function rewriteDiff(inputStr: string): string {
611+
const lines = inputStr.split('\n')
612+
const rewrittenLines = lines.slice(0, 5).map((line) => {
613+
line = line.replace(/\\\\/g, '/')
614+
line = line.replace(/("a\/[^"]*)/g, (match, p1) => p1)
615+
line = line.replace(/("b\/[^"]*)/g, (match, p1) => p1)
616+
line = line.replace(/"/g, '')
617+
618+
return line
619+
})
620+
const outputLines = [...rewrittenLines, ...lines.slice(5)]
621+
const outputStr = outputLines.join('\n')
622+
623+
return outputStr
624+
}

packages/core/src/shared/utilities/textDocumentUtilities.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,3 +267,9 @@ class ReadonlyDocument {
267267
}
268268

269269
export const readonlyDocument = new ReadonlyDocument()
270+
271+
export async function getTextContent(uri: vscode.Uri) {
272+
const document = await vscode.workspace.openTextDocument(uri)
273+
const content = document.getText()
274+
return content
275+
}

packages/core/src/shared/utilities/vsCodeUtils.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,3 @@ export function subscribeOnce<T>(event: vscode.Event<T>): vscode.Event<T> {
254254
return result
255255
}
256256
}
257-
258-
export async function getTextContent(uri: vscode.Uri) {
259-
const document = await vscode.workspace.openTextDocument(uri)
260-
const content = document.getText()
261-
return content
262-
}

0 commit comments

Comments
 (0)