edf2csv 0.8.91 → 0.8.92

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.
@@ -10,6 +10,8 @@ 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';
13
+ // A destination is whatever the caller's shell handed over; see printable's own comment.
14
+ import { printable } from '../format/unprintable.js';
13
15
  import { EdfFile } from '../edf/reader.js';
14
16
  import { describeFormat, formatRate, formatRates, formatWallClock, startsFormula } from '../edf/header.js';
15
17
  import { EdfError } from '../edf/errors.js';
@@ -345,6 +347,22 @@ async function assertInputDoesNotOverlapOutputs(inputPath, outputDir, file, plan
345
347
  }
346
348
  }
347
349
  async function prepareOutputDir(dir, force) {
350
+ /*
351
+ The destination, quoted into every refusal below, and shown rather than pasted.
352
+
353
+ `--out` is whatever the caller's shell handed over, and `printableLines` escapes every
354
+ control byte in a message except the one that makes a line break — it splits on those
355
+ first, to keep the author's own lines. So a newline in a destination cut the refusal's
356
+ first line in half:
357
+
358
+ error: "out/ex
359
+ ists" already exists.
360
+
361
+ which is the line this tool's comments keep insisting stays whole, because it is the one a
362
+ log gets grepped for. Same in `EdfFile.open`'s path and in a `--channels` term; all three
363
+ go through `printable` now, where the summary and the report have always put them.
364
+ */
365
+ const shownDir = printable(dir);
348
366
  /*
349
367
  Claim the directory with a single atomic mkdir rather than asking whether it exists
350
368
  and then creating it.
@@ -369,9 +387,9 @@ async function prepareOutputDir(dir, force) {
369
387
  // directory inside a file". Name the real obstacle instead of the errno.
370
388
  const info = await stat(parent).catch(() => null);
371
389
  if (info && !info.isDirectory()) {
372
- throw new ConversionError('OUTPUT_UNWRITABLE', `Cannot create "${dir}": "${parent}" is a file, not a directory.`, 'Choose a destination whose parent directories are directories, with --out.');
390
+ throw new ConversionError('OUTPUT_UNWRITABLE', `Cannot create "${shownDir}": "${printable(parent)}" is a file, not a directory.`, 'Choose a destination whose parent directories are directories, with --out.');
373
391
  }
374
- throw new ConversionError('OUTPUT_UNWRITABLE', `Cannot create "${dir}": ${describeFsError(cause)}.`, createHint(cause));
392
+ throw new ConversionError('OUTPUT_UNWRITABLE', `Cannot create "${shownDir}": ${describeFsError(cause)}.`, createHint(cause));
375
393
  }
376
394
  }
377
395
  let claimed = true;
@@ -380,7 +398,7 @@ async function prepareOutputDir(dir, force) {
380
398
  }
381
399
  catch (cause) {
382
400
  if (cause.code !== 'EEXIST') {
383
- throw new ConversionError('OUTPUT_UNWRITABLE', `Cannot create "${dir}": ${describeFsError(cause)}.`, createHint(cause));
401
+ throw new ConversionError('OUTPUT_UNWRITABLE', `Cannot create "${shownDir}": ${describeFsError(cause)}.`, createHint(cause));
384
402
  }
385
403
  claimed = false;
386
404
  }
@@ -389,7 +407,7 @@ async function prepareOutputDir(dir, force) {
389
407
  // --force means "replace my previous output", not "write output files into
390
408
  // whatever this happens to be". Pointing it at a regular file needs saying so.
391
409
  if (existing && !existing.isDirectory()) {
392
- throw new ConversionError('OUTPUT_UNWRITABLE', `"${dir}" is a file, but the converted data needs a directory.`, 'Choose a directory with --out.');
410
+ throw new ConversionError('OUTPUT_UNWRITABLE', `"${shownDir}" is a file, but the converted data needs a directory.`, 'Choose a directory with --out.');
393
411
  }
394
412
  /*
395
413
  A link to nothing, which `stat` cannot see and `mkdir` will not write through.
@@ -411,7 +429,7 @@ async function prepareOutputDir(dir, force) {
411
429
  a mount that has since gone.
412
430
  */
413
431
  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 ` +
432
+ throw new ConversionError('OUTPUT_UNWRITABLE', `"${shownDir}" is a symbolic link to something that does not exist, so nothing can be ` +
415
433
  `written there.`, 'Remove the link, or choose a directory with --out. --force writes into a directory ' +
416
434
  'that is already there, and a link to nowhere is not one.');
417
435
  }
@@ -433,7 +451,7 @@ async function prepareOutputDir(dir, force) {
433
451
  metadata.json describing only the second — which is exactly the outcome a reader who
434
452
  was told the directory would be replaced does not expect, and does not check for.
435
453
  */
436
- throw new ConversionError('OUTPUT_EXISTS', `"${dir}" already exists.`, 'Pass --force to write into it, leaving whatever else it holds, or --out to choose ' +
454
+ throw new ConversionError('OUTPUT_EXISTS', `"${shownDir}" already exists.`, 'Pass --force to write into it, leaving whatever else it holds, or --out to choose ' +
437
455
  'a different directory.');
438
456
  }
439
457
  }