Skip to content

Commit 513383c

Browse files
authored
Merge pull request #93 from Automattic/GH-73
fix: handle file truncation
2 parents 8b6d43f + b7d30aa commit 513383c

File tree

3 files changed

+59
-8
lines changed

3 files changed

+59
-8
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## [Unreleased]
44

5+
## [1.0.1](https://github.com/Automattic/vscode-logwatcher/releases/tag/v1.0.1)
6+
7+
* Properly handle file truncation
8+
59
## [1.0.0](https://github.com/Automattic/vscode-logwatcher/releases/tag/v1.0.0)
610

711
* First official release
@@ -17,4 +21,4 @@
1721

1822
## [0.0.1](https://github.com/Automattic/vscode-logwatcher/releases/tag/v0.0.1)
1923

20-
- Initial release.
24+
* Initial release.

src/test/suite/watchfilecommand.test.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { deepEqual, equal, match, notEqual } from 'node:assert/strict';
22
import { EventEmitter, once } from 'node:events';
33
import { WriteStream, createWriteStream } from 'node:fs';
4-
import { mkdtemp, rm, unlink, writeFile } from 'node:fs/promises';
4+
import { mkdtemp, rm, unlink, writeFile, truncate } from 'node:fs/promises';
55
import { EOL, platform, tmpdir } from 'node:os';
66
import { join } from 'node:path';
77
import { setTimeout } from 'node:timers/promises';
@@ -177,4 +177,41 @@ suite('WatchFileCommand', function () {
177177
const actual = getFilenames();
178178
deepEqual(actual, expected);
179179
});
180+
181+
182+
test('file truncation', async function () {
183+
const fname = join(tmpDir, '0006.txt');
184+
185+
const expectedContent = '0123456789';
186+
await writeFile(fname, expectedContent);
187+
188+
const [editor, emitter] = await Promise.all([
189+
waitForOutputWindow(`extension-output-`),
190+
commands.executeCommand<EventEmitter>('logwatcher.watchFile', fname),
191+
]);
192+
193+
notEqual(editor, undefined);
194+
notEqual(emitter, undefined);
195+
196+
if (!editor.document.getText()) {
197+
await waitForVisibleRangesChange(editor);
198+
}
199+
200+
let actual = editor.document.getText();
201+
equal(actual, expectedContent);
202+
203+
const waitForVisibleRangesChangePromise = waitForVisibleRangesChange(editor);
204+
const onceFileChangedPromise = once(emitter, 'fileChanged');
205+
206+
const expectedSize = 5;
207+
await truncate(fname, expectedSize);
208+
209+
await Promise.all([
210+
waitForVisibleRangesChangePromise,
211+
onceFileChangedPromise,
212+
]);
213+
214+
actual = editor.document.getText();
215+
equal(actual, expectedContent + expectedContent.slice(0, expectedSize));
216+
});
180217
});

src/watchfilecommand.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,23 @@ async function setUpWatcher(filename: string): Promise<Resource | null> {
109109
let fd: FileHandle | undefined;
110110
let stats: FileStat | null;
111111
try {
112-
[fd, stats] = await Promise.all([open(filename, 'r'), statFile(filename)]);
113-
112+
stats = await statFile(filename);
114113
if (stats) {
115-
const buffer = Buffer.alloc(stats.size - offset);
116-
await fd.read(buffer, 0, buffer.length, offset);
117-
offset += buffer.length;
118-
outputChannel.append(buffer.toString('ascii'));
114+
if (stats.size > offset) {
115+
fd = await open(filename, 'r');
116+
const buffer = Buffer.alloc(stats.size - offset);
117+
await fd.read(buffer, 0, buffer.length, offset);
118+
offset += buffer.length;
119+
outputChannel.append(buffer.toString('ascii'));
120+
} else {
121+
offset = stats.size;
122+
const data = await readInitialData(filename, offset);
123+
if (typeof data === 'string') {
124+
outputChannel.append(data);
125+
} else {
126+
throw data;
127+
}
128+
}
119129
}
120130
} catch (err) {
121131
outputChannel.appendLine(`*** Failed to read file ${filename}: ${(err as Error).message}`);

0 commit comments

Comments
 (0)