Skip to content

Commit 4cd53bd

Browse files
committed
merge: undo merge
1 parent cee9f55 commit 4cd53bd

File tree

7 files changed

+47
-22
lines changed

7 files changed

+47
-22
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Bug Fix",
3+
"description": "Amazon Q: Fix code upload error when using /dev or /doc on Remote SSH"
4+
}

packages/amazonq/test/unit/amazonqFeatureDev/util/files.test.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,11 @@ import {
1111
maxRepoSizeBytes,
1212
} from 'aws-core-vscode/amazonqFeatureDev'
1313
import { assertTelemetry, getWorkspaceFolder, TestFolder } from 'aws-core-vscode/test'
14-
import { fs, AmazonqCreateUpload } from 'aws-core-vscode/shared'
14+
import { fs, AmazonqCreateUpload, ZipStream } from 'aws-core-vscode/shared'
1515
import { MetricName, Span } from 'aws-core-vscode/telemetry'
1616
import sinon from 'sinon'
1717
import { CodeWhispererSettings } from 'aws-core-vscode/codewhisperer'
1818

19-
import AdmZip from 'adm-zip'
20-
2119
const testDevfilePrepareRepo = async (devfileEnabled: boolean) => {
2220
const files: Record<string, string> = {
2321
'file.md': 'test content',
@@ -38,8 +36,8 @@ const testDevfilePrepareRepo = async (devfileEnabled: boolean) => {
3836
}
3937

4038
const expectedFiles = !devfileEnabled
41-
? ['./file.md', './.gitignore']
42-
: ['./devfile.yaml', './file.md', './.gitignore', './abc.jar', 'data/logo.ico']
39+
? ['file.md', '.gitignore']
40+
: ['devfile.yaml', 'file.md', '.gitignore', 'abc.jar', 'data/logo.ico']
4341

4442
const workspace = getWorkspaceFolder(folder.path)
4543
sinon
@@ -71,8 +69,8 @@ const testPrepareRepoData = async (
7169
}
7270

7371
// Unzip the buffer and compare the entry names
74-
const zip = new AdmZip(result.zipFileBuffer)
75-
const actualZipEntries = zip.getEntries().map((entry) => entry.entryName)
72+
const zipEntries = await ZipStream.unzip(result.zipFileBuffer)
73+
const actualZipEntries = zipEntries.map((entry) => entry.filename)
7674
actualZipEntries.sort((a, b) => a.localeCompare(b))
7775
assert.deepStrictEqual(actualZipEntries, expectedFiles)
7876
}
@@ -89,7 +87,7 @@ describe('file utils', () => {
8987
await folder.write('file2.md', 'test content')
9088
const workspace = getWorkspaceFolder(folder.path)
9189

92-
await testPrepareRepoData(workspace, ['./file1.md', './file2.md'])
90+
await testPrepareRepoData(workspace, ['file1.md', 'file2.md'])
9391
})
9492

9593
it('prepareRepoData ignores denied file extensions', async function () {

packages/core/src/amazonqFeatureDev/util/files.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@ import * as vscode from 'vscode'
77
import * as path from 'path'
88
import { collectFiles } from '../../shared/utilities/workspaceUtils'
99

10-
import AdmZip from 'adm-zip'
1110
import { ContentLengthError, PrepareRepoFailedError } from '../errors'
1211
import { getLogger } from '../../shared/logger/logger'
1312
import { maxFileSizeBytes } from '../limits'
14-
import { createHash } from 'crypto'
1513
import { CurrentWsFolders } from '../types'
1614
import { hasCode, ToolkitError } from '../../shared/errors'
1715
import { AmazonqCreateUpload, Span, telemetry as amznTelemetry } from '../../shared/telemetry/telemetry'
@@ -20,8 +18,7 @@ import { maxRepoSizeBytes } from '../constants'
2018
import { isCodeFile } from '../../shared/filetypes'
2119
import { fs } from '../../shared'
2220
import { CodeWhispererSettings } from '../../codewhisperer'
23-
24-
const getSha256 = (file: Buffer) => createHash('sha256').update(file).digest('base64')
21+
import { ZipStream } from '../../shared/utilities/zipStream'
2522

2623
export async function checkForDevFile(root: string) {
2724
const devFilePath = root + '/devfile.yaml'
@@ -37,7 +34,7 @@ export async function prepareRepoData(
3734
workspaceFolders: CurrentWsFolders,
3835
telemetry: TelemetryHelper,
3936
span: Span<AmazonqCreateUpload>,
40-
zip: AdmZip = new AdmZip()
37+
zip: ZipStream = new ZipStream()
4138
) {
4239
try {
4340
const autoBuildSetting = CodeWhispererSettings.instance.getAutoBuildSetting()
@@ -77,11 +74,12 @@ export async function prepareRepoData(
7774
continue
7875
}
7976
totalBytes += fileSize
80-
81-
const zipFolderPath = path.dirname(file.zipFilePath)
77+
// Paths in zip should be POSIX compliant regardless of OS
78+
// Reference: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
79+
const posixPath = file.zipFilePath.split(path.sep).join(path.posix.sep)
8280

8381
try {
84-
zip.addLocalFile(file.fileUri.fsPath, zipFolderPath)
82+
zip.writeFile(file.fileUri.fsPath, posixPath)
8583
} catch (error) {
8684
if (error instanceof Error && error.message.includes('File not found')) {
8785
// No-op: Skip if file was deleted or does not exist
@@ -111,11 +109,12 @@ export async function prepareRepoData(
111109

112110
telemetry.setRepositorySize(totalBytes)
113111
span.record({ amazonqRepositorySize: totalBytes })
112+
const zipResult = await zip.finalize()
114113

115-
const zipFileBuffer = zip.toBuffer()
114+
const zipFileBuffer = zipResult.streamBuffer.getContents() || Buffer.from('')
116115
return {
117116
zipFileBuffer,
118-
zipFileChecksum: getSha256(zipFileBuffer),
117+
zipFileChecksum: zipResult.hash,
119118
}
120119
} catch (error) {
121120
getLogger().debug(`featureDev: Failed to prepare repo: ${error}`)

packages/core/src/shared/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export * from './localizedText'
4848
export * as env from './vscode/env'
4949
export * from './vscode/commands2'
5050
export * from './utilities/pathUtils'
51+
export * from './utilities/zipStream'
5152
export * from './errors'
5253
export * as messages from './utilities/messages'
5354
export * as errors from './errors'

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { WritableStreamBuffer } from 'stream-buffers'
66
import crypto from 'crypto'
77
import { readFileAsString } from '../filesystemUtilities'
88
// Use require instead of import since this package doesn't support commonjs
9-
const { ZipWriter, TextReader } = require('@zip.js/zip.js')
9+
const { ZipWriter, TextReader, ZipReader, Uint8ArrayReader } = require('@zip.js/zip.js')
1010
import { getLogger } from '../logger/logger'
1111

1212
export interface ZipStreamResult {
@@ -15,6 +15,10 @@ export interface ZipStreamResult {
1515
streamBuffer: WritableStreamBuffer
1616
}
1717

18+
export type ZipReaderResult = {
19+
filename: string
20+
}
21+
1822
export type ZipStreamProps = {
1923
hashAlgorithm: 'md5' | 'sha256'
2024
maxNumberOfFileStreams: number
@@ -150,4 +154,13 @@ export class ZipStream {
150154
streamBuffer: this._streamBuffer,
151155
}
152156
}
157+
158+
public static async unzip(zipBuffer: Buffer): Promise<ZipReaderResult[]> {
159+
const reader = new ZipReader(new Uint8ArrayReader(new Uint8Array(zipBuffer)))
160+
try {
161+
return await reader.getEntries()
162+
} finally {
163+
await reader.close()
164+
}
165+
}
153166
}

packages/core/src/test/shared/utilities/zipStream.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,15 @@ describe('zipStream', function () {
6060
assert.strictEqual(result.hash, expectedMd5)
6161
assert.strictEqual(result.sizeInBytes, (await fs.stat(zipPath)).size)
6262
})
63+
64+
it('should unzip from a buffer', async function () {
65+
const zipStream = new ZipStream()
66+
await zipStream.writeString('foo bar', 'file.txt')
67+
const result = await zipStream.finalize()
68+
69+
const zipBuffer = result.streamBuffer.getContents()
70+
assert.ok(zipBuffer)
71+
const zipEntries = await ZipStream.unzip(zipBuffer)
72+
assert.strictEqual(zipEntries[0].filename, 'file.txt')
73+
})
6374
})

packages/core/src/testInteg/perf/prepareRepoData.test.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ function performanceTestWrapper(numFiles: number, fileSize: number) {
3030
getEqualOSTestOptions({
3131
userCpuUsage: 200,
3232
systemCpuUsage: 35,
33-
heapTotal: 4,
33+
heapTotal: 20,
3434
}),
3535
`handles ${numFiles} files of size ${fileSize} bytes`,
3636
function () {
@@ -63,8 +63,7 @@ function verifyResult(setup: setupResult, result: resultType, telemetry: Telemet
6363
assert.strictEqual(Buffer.isBuffer(result.zipFileBuffer), true)
6464
assert.strictEqual(telemetry.repositorySize, expectedSize)
6565
assert.strictEqual(result.zipFileChecksum.length, 44)
66-
67-
assert.ok(getFsCallsUpperBound(setup.fsSpy) <= setup.numFiles * 4, 'total system calls should be under 4 per file')
66+
assert.ok(getFsCallsUpperBound(setup.fsSpy) <= setup.numFiles * 8, 'total system calls should be under 8 per file')
6867
}
6968

7069
describe('prepareRepoData', function () {

0 commit comments

Comments
 (0)