Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions README.md

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions devguide.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,16 @@ All output goes through `src/output.ts`. Pick the function by who the message is
| `print(item, delimiter, tail, stream)` | Always | The result. Puts the delimiter after each item, or only between them without a tail. Without a delimiter it is a line break, unless the item already ends with one. | A name, the content of a file, a match |
| `printDone()` | At the end of a run, also when it is stopped | Ends stdout and stderr with a line break when `--nl` is set | |
| `info(name)` | Unless `--quiet` | The name of an affected file. stdout, or stderr when stdout has content. | `a.md` |
| `warn(msg)` | Unless `--quiet` | Something is likely a mistake, but the run goes on. Also added to `status.warnings`. | `Data is piped in, but no flag tells what to do with it` |
| `warn(msg)` | Unless `--quiet` | Something is likely a mistake, or there is nothing to do, but the run goes on. Starts with 🟡. Also added to `status.warnings`. | `0 files found` |
| `error(msg, data)` | Unless `--quiet-total` | Something went wrong. Starts with ❌. The run goes on, unless `--halt` is set: then a panic is thrown. Also added to `status.errors`, so the CLI gives the exit code 2. | `File not found: a.md` |
| `panic(msg, data, help)` | Unless `--quiet-total` | Something went wrong and the run can not go on. Starts with ❌ and ends with `No further processing.` Throws a panic, and the CLI exits with 3. Also added to `status.errors`. | `No data piped into replacement` |
| `checkFailed(text)` | Unless `--quiet-total` | A check from `--expect-*` that is not met. An error, also in `status.checks`, so the CLI gives the exit code 1 when the failed checks are the only errors. | `Expected a diff, but nothing was changed` |
| `panic(msg, data, help)` | Unless `--quiet-total` | Something went wrong and the run can not go on. Starts with ❌, ends with `No further processing.`, and throws a panic, so the CLI exits with 3. Also added to `status.errors`. | `No data piped into replacement` |
| `chat(msg)` | `--verbose`, also with `--quiet`, but not with `--quiet-total` | The user: what happens to each file. Only ever to stderr. Also kept in `engine.steps` of the status report. | `Open sync: a.md`, `Nothing changed in: a.md` |

- What the run did is in the status report: the engine resolves with it, and `--status` prints it. So there is no extra debug output to print along the way.
- `--debug` prints only the status report, with what went into the engine and what it did.
- `warn()`, `error()` and `panic()` add to the status report as they go, also when the quiet flags hide what they print.
- The exit code is 0 when the run is done, 2 when a file gave an error, and 3 for a panic or wrong flags. 1 is kept for a check that says no, like `grep`. See Exit codes in the README.
- `warn()`, `error()`, `checkFailed()` and `panic()` add to the status report as they go, also when the quiet flags hide what they print.
- The exit code is 0 when the run is done, 1 when a check from `--expect-*` is not met, 2 when a file gave an error, and 3 for a panic or wrong flags. See Exit codes in the README.

## Tests

Expand Down
13 changes: 6 additions & 7 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,12 +312,11 @@ const yargs = require('yargs')
''
)

.boolean('p')
.alias('p', 'pipe')
.describe('p', `Read the piped data and make it available to --js as \`pipe\`.`)

.boolean('js-pipe')
.describe('js-pipe', `Shorthand for --js --pipe (-jp).`)
.describe(
'js-pipe',
`Treat the replacement as javascript, and give the code the piped data as \`pipe\`.`
)

.boolean('g')
.alias('g', 'glob-pipe')
Expand All @@ -326,7 +325,7 @@ const yargs = require('yargs')
'Each line of the piped data is a path or a glob of the files to work on. They are used together with the ones given as arguments.'
)
// The piped data can only be one thing
.conflicts('g', ['R', 'p', 'js-pipe'])
.conflicts('g', ['R', 'js-pipe'])

.boolean('null-in')
.describe(
Expand All @@ -352,7 +351,7 @@ The code has access to the following variables:
\`fs\` from node,
\`path\` from node,
\`globs\` from npm,
\`pipe\`: the data piped into the command with --pipe (null if no piped data, and \`pipe_\` is \`❌ \`),
\`pipe\`: the data piped into the command with --js-pipe (null if no piped data, and \`pipe_\` is \`❌ \`),
\`find\`: pattern searched for (the needle),
\`text\`: full text being searched i.e. file content or piped data (the haystack),
\`bytes\`: total size of the haystack in bytes,
Expand Down
14 changes: 2 additions & 12 deletions src/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ async function run(config) {
if (config.globPipe) {
if (config.replacementPipe || config.pipe) {
panic(
'--glob-pipe can not be used with --replacement-pipe or --pipe, as the piped data can only be one thing'
'--glob-pipe can not be used with --replacement-pipe or --js-pipe, as the piped data can only be one thing'
);
}
config.pipedDataUsed = true;
Expand Down Expand Up @@ -521,18 +521,8 @@ function pipeType(config, piped) {
}

function handlePipedData(config) {
// With files the piped data is only read when a flag asks for it, and then the flag uses it
if (config.includeGlob.length) {
// Empty piped data (or only a line break) is not worth a warning
if (
!config.replacementJs &&
!config.pipedDataUsed &&
config.pipedData &&
'\n' !== config.pipedData &&
'\r\n' !== config.pipedData
) {
warn('Data is piped in, but no flag tells what to do with it. It is not used.');
}

return false;
}

Expand Down
2 changes: 1 addition & 1 deletion test/cli/glob-pipe.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('--glob-pipe', () => {
});
});

test.each([['--replacement-pipe'], ['--pipe'], ['--js-pipe']])(
test.each([['--replacement-pipe'], ['--js-pipe']])(
'can not be used with %s, as the piped data can only be one thing',
async flag => {
fs.writeFileSync('my.file', 'foobar\n');
Expand Down
52 changes: 7 additions & 45 deletions test/cli/pipe.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ import fs from 'fs';
import {$} from 'bun';
import {cli, sh} from '../helper.js';

const warning = ' 🟡 Data is piped in, but no flag tells what to do with it. It is not used.\n\n';

describe('--pipe and --js-pipe', () => {
test('without --pipe the code does not get the piped data', async () => {
describe('--js-pipe', () => {
test('without it the code does not get the piped data', async () => {
fs.writeFileSync('my.file', 'foobar\n');
expect(await sh($`echo -n x | bun ${cli} foo pipe my.file -o --js`)).toEqual({
out: 'nullbar\n',
Expand All @@ -15,16 +13,8 @@ describe('--pipe and --js-pipe', () => {
});
});

test('the code gets the piped data with --js --pipe', async () => {
fs.writeFileSync('my.file', 'foobar\n');
expect((await sh($`echo -n x | bun ${cli} foo pipe my.file -o --js --pipe`)).out).toBe(
'xbar\n'
);
});

test('the code gets the piped data with -jp and --js-pipe', async () => {
test('gives the code the piped data as pipe', async () => {
fs.writeFileSync('my.file', 'foobar\n');
expect((await sh($`echo -n x | bun ${cli} foo pipe my.file -o -jp`)).out).toBe('xbar\n');
expect((await sh($`echo -n x | bun ${cli} foo pipe my.file -o --js-pipe`)).out).toBe('xbar\n');
});

Expand All @@ -34,39 +24,11 @@ describe('--pipe and --js-pipe', () => {
'xbar\n'
);
});
});

describe('the warning that piped data is not used', () => {
test('is given when data is read with --pipe, but not used', async () => {
fs.writeFileSync('my.file', 'foobar\n');
expect(await sh($`echo -n x | bun ${cli} o x my.file --pipe`)).toEqual({
out: 'my.file\n',
err: warning,
exit: 0,
});
expect(fs.readFileSync('my.file', 'utf8')).toBe('fxxbar\n');
});

test('is not given without --pipe, as the data is not read', async () => {
fs.writeFileSync('my.file', 'foobar\n');
expect((await sh($`echo -n x | bun ${cli} o x my.file`)).err).toBe('');
});

test('is not given with --quiet', async () => {
fs.writeFileSync('my.file', 'foobar\n');
expect((await sh($`echo -n x | bun ${cli} o x my.file --pipe -q`)).err).toBe('');
});

test('is not given when the data is used', async () => {
fs.writeFileSync('my.file', 'foobar\n');
expect((await sh($`echo -n x | bun ${cli} b _ my.file -R`)).err).toBe('');
expect((await sh($`echo -n x | bun ${cli} b pipe my.file --js-pipe`)).err).toBe('');
});

test('is not given when nothing, or only a line break, is piped in', async () => {
test.each([['--pipe'], ['-p']])('%s is gone, as --js-pipe does the same', async flag => {
fs.writeFileSync('my.file', 'foobar\n');
expect((await sh($`echo -n '' | bun ${cli} o x my.file --pipe`)).err).toBe('');
expect((await sh($`echo '' | bun ${cli} o x my.file --pipe`)).err).toBe('');
expect((await sh($`bun ${cli} o x my.file --pipe < ${new Response('\r\n')}`)).err).toBe('');
const result = await sh($`echo -n x | bun ${cli} foo pipe my.file -o --js ${flag}`);
expect(result.exit).toBe(3);
expect(result.err).toContain('Unknown argument');
});
});
4 changes: 0 additions & 4 deletions test/cli/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,6 @@ assert "printf x | rexreplace 'b' _ my.file -o --replacement-pipe" 'fooxa
reset
assert "printf x | rexreplace 'foo' 'pipe' my.file -o --js-pipe" 'xbar'

# Data that is piped in but not used gives a warning
reset
assert "printf x | rexreplace 'o' 'x' my.file --pipe 2>&1 >/dev/null | grep -c 'Data is piped in'" '1'


# The names of the changed files go to stdout, so they can be piped on
reset
Expand Down
9 changes: 1 addition & 8 deletions test/engine/verbose.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,6 @@ describe('--verbose', () => {
);
});

test('is not needed to be told that piped data is not used (a warning since #719)', async () => {
fs.writeFileSync('my.file', 'foobar');
const config = {includeGlob: ['my.file'], pipedData: 'boo'};
expect((await rr('o', 'x', {...config, verbose: true})).err).toContain('Data is piped in');
expect((await rr('x', 'o', config)).err).toContain('Data is piped in');
});

test('never writes to stdout', async () => {
expect((await rr('o', 'x', {pipedData: 'foobar', verbose: true})).out).toBe('fxxbar');
});
Expand Down Expand Up @@ -80,7 +73,7 @@ describe('--verbose', () => {
verbose: true,
replacementJs: true,
};
expect((await rr('foo', 'pipe', config)).err).not.toContain('Data is piped in');
await rr('foo', 'pipe', config);
expect(fs.readFileSync('my.file', 'utf8')).toBe('boobar');
});
});
Expand Down
2 changes: 1 addition & 1 deletion test/fix/711.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ describe('#711 --glob-pipe', () => {

test.each([
['--replacement-pipe', {replacementPipe: true}],
['--pipe', {pipe: true}],
['--js-pipe', {replacementJs: true, pipe: true}],
])('can not be used with %s, as the piped data can only be one thing', async (name, flags) => {
fs.writeFileSync('a.file', 'foo');
const result = await rr('o', 'x', {pipedData: 'a.file', globPipe: true, ...flags});
Expand Down
76 changes: 0 additions & 76 deletions test/fix/719.test.js

This file was deleted.

11 changes: 2 additions & 9 deletions test/fix/742.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,8 @@ describe('#742 the engine resolves with a status', () => {
});

test('with the warnings, also when --quiet hides them', async () => {
fs.writeFileSync('a.file', 'foo');
const status = await rrStatus('o', 'x', {
includeGlob: ['a.file'],
pipedData: 'x',
quiet: true,
});
expect(status.warnings).toEqual([
'Data is piped in, but no flag tells what to do with it. It is not used.',
]);
const status = await rrStatus('o', 'x', {includeGlob: ['nope.file'], quiet: true});
expect(status.warnings).toEqual(['0 files found']);
});
});

Expand Down
Loading