edf2csv 0.8.64 → 0.8.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,7 @@
6
6
  * matter how many output tables it produces, and memory stays flat.
7
7
  */
8
8
  import { createWriteStream, fstatSync } from 'node:fs';
9
- import { mkdir, readdir, stat, writeFile } from 'node:fs/promises';
9
+ import { lstat, mkdir, readdir, stat, writeFile } from 'node:fs/promises';
10
10
  import { finished } from 'node:stream/promises';
11
11
  import { createGzip, gzipSync } from 'node:zlib';
12
12
  import path from 'node:path';
@@ -391,6 +391,30 @@ async function prepareOutputDir(dir, force) {
391
391
  if (existing && !existing.isDirectory()) {
392
392
  throw new ConversionError('OUTPUT_UNWRITABLE', `"${dir}" is a file, but the converted data needs a directory.`, 'Choose a directory with --out.');
393
393
  }
394
+ /*
395
+ A link to nothing, which `stat` cannot see and `mkdir` will not write through.
396
+
397
+ `stat` follows symbolic links, so a dangling one leaves `existing` null and fell through
398
+ to the sentence below — which is the one claim that is not true of it:
399
+
400
+ $ edf2csv rec.edf --out link-to-nowhere
401
+ error: "link-to-nowhere" already exists.
402
+ Pass --force to overwrite it, or --out to choose a different directory.
403
+
404
+ Nothing is there. And following that advice made it worse: `--force` reached the writer
405
+ and came back as `Writing to "link-to-nowhere" failed: part of the path does not exist.
406
+ The files written so far are incomplete and should not be used` — a conversion failure,
407
+ about files that were never written, advising the reader to make sure nothing is
408
+ removing a directory that never existed.
409
+
410
+ A broken link in a batch's destination is how this arrives: the run before it wrote into
411
+ a mount that has since gone.
412
+ */
413
+ if (!existing && (await lstat(dir).catch(() => null))) {
414
+ throw new ConversionError('OUTPUT_UNWRITABLE', `"${dir}" is a symbolic link to something that does not exist, so nothing can be ` +
415
+ `written there.`, 'Remove the link, or choose a directory with --out. --force replaces a previous ' +
416
+ 'output directory and cannot follow a link to nowhere.');
417
+ }
394
418
  if (!force) {
395
419
  throw new ConversionError('OUTPUT_EXISTS', `"${dir}" already exists.`, 'Pass --force to overwrite it, or --out to choose a different directory.');
396
420
  }