Skip to content

Commit c447c8b

Browse files
committed
claude fixes a test
1 parent 8e61d52 commit c447c8b

File tree

1 file changed

+84
-43
lines changed

1 file changed

+84
-43
lines changed

src/extract.ts

Lines changed: 84 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -69,69 +69,110 @@ export async function extractTarGz(
6969
} | null = null
7070

7171
return new Promise((resolve, reject) => {
72+
let isProcessing = false
73+
const chunks: Buffer[] = []
74+
7275
const processChunk = async (chunk: Buffer) => {
73-
buffer = Buffer.concat([buffer, chunk])
76+
if (isProcessing) {
77+
chunks.push(chunk)
78+
return
79+
}
7480

75-
while (buffer.length >= 512) {
76-
if (!currentFile) {
77-
// Parse header
78-
const header = parseTarHeader(buffer.subarray(0, 512))
79-
if (!header) {
80-
// End of archive or invalid header
81-
buffer = buffer.subarray(512)
82-
continue
83-
}
81+
isProcessing = true
82+
buffer = Buffer.concat([buffer, chunk])
8483

85-
if (header.type === 'file' && header.size > 0) {
86-
currentFile = { name: header.name, size: header.size }
87-
const outputPath = join(resolvedOutputDir, header.name)
84+
// Process any queued chunks
85+
while (chunks.length > 0) {
86+
const nextChunk = chunks.shift()
87+
if (nextChunk) {
88+
buffer = Buffer.concat([buffer, nextChunk])
89+
}
90+
}
8891

89-
// Ensure directory exists
90-
await fs.mkdir(dirname(outputPath), { recursive: true })
91-
currentFile.stream = createWriteStream(outputPath)
92-
}
92+
try {
93+
while (buffer.length >= 512) {
94+
if (!currentFile) {
95+
// Parse header
96+
const header = parseTarHeader(buffer.subarray(0, 512))
97+
if (!header) {
98+
// End of archive or invalid header
99+
buffer = buffer.subarray(512)
100+
continue
101+
}
93102

94-
buffer = buffer.subarray(512) // Skip header
95-
} else {
96-
// Extract file content
97-
const remainingSize = currentFile.size
98-
const availableData = Math.min(remainingSize, buffer.length)
103+
if (header.type === 'file' && header.size > 0) {
104+
currentFile = { name: header.name, size: header.size }
105+
const outputPath = join(resolvedOutputDir, header.name)
99106

100-
if (availableData > 0 && currentFile.stream) {
101-
currentFile.stream.write(buffer.subarray(0, availableData))
102-
currentFile.size -= availableData
103-
buffer = buffer.subarray(availableData)
104-
}
107+
// Ensure directory exists
108+
await fs.mkdir(dirname(outputPath), { recursive: true })
109+
currentFile.stream = createWriteStream(outputPath)
110+
}
105111

106-
if (currentFile.size === 0) {
107-
// File complete
108-
if (currentFile.stream) {
109-
currentFile.stream.end()
112+
buffer = buffer.subarray(512) // Skip header
113+
} else {
114+
// Extract file content
115+
const remainingSize = currentFile.size
116+
const availableData = Math.min(remainingSize, buffer.length)
117+
118+
if (availableData > 0 && currentFile.stream) {
119+
currentFile.stream.write(buffer.subarray(0, availableData))
120+
currentFile.size -= availableData
121+
buffer = buffer.subarray(availableData)
110122
}
111-
currentFile = null
112123

113-
// Skip padding to 512-byte boundary
114-
const paddingSize = (512 - (availableData % 512)) % 512
115-
if (buffer.length >= paddingSize) {
116-
buffer = buffer.subarray(paddingSize)
124+
if (currentFile.size === 0) {
125+
// File complete - wait for stream to finish
126+
if (currentFile.stream) {
127+
await new Promise<void>((streamResolve, streamReject) => {
128+
currentFile?.stream?.once('finish', streamResolve)
129+
currentFile?.stream?.once('error', streamReject)
130+
currentFile?.stream?.end()
131+
})
132+
}
133+
currentFile = null
134+
135+
// Skip padding to 512-byte boundary
136+
const paddingSize = (512 - (availableData % 512)) % 512
137+
if (buffer.length >= paddingSize) {
138+
buffer = buffer.subarray(paddingSize)
139+
}
140+
} else if (buffer.length < remainingSize) {
141+
// Need more data
142+
break
117143
}
118-
} else if (buffer.length < remainingSize) {
119-
// Need more data
120-
break
121144
}
122145
}
146+
} catch (error) {
147+
reject(error)
148+
return
123149
}
150+
151+
isProcessing = false
124152
}
125153

126154
gunzip.on('data', (chunk: Buffer) => {
127155
processChunk(chunk).catch(reject)
128156
})
129157

130-
gunzip.on('end', () => {
131-
if (currentFile?.stream) {
132-
currentFile.stream.end()
158+
gunzip.on('end', async () => {
159+
try {
160+
// Wait for any pending processing
161+
while (isProcessing) {
162+
await new Promise((resolve) => setTimeout(resolve, 1))
163+
}
164+
165+
if (currentFile?.stream) {
166+
await new Promise<void>((streamResolve, streamReject) => {
167+
currentFile?.stream?.once('finish', streamResolve)
168+
currentFile?.stream?.once('error', streamReject)
169+
currentFile?.stream?.end()
170+
})
171+
}
172+
resolve()
173+
} catch (error) {
174+
reject(error)
133175
}
134-
resolve()
135176
})
136177

137178
gunzip.on('error', reject)

0 commit comments

Comments
 (0)