Skip to content

Commit

Permalink
fix: Replace home-made line parser with split2
Browse files Browse the repository at this point in the history
  • Loading branch information
quentinrossetti committed Feb 6, 2022
1 parent f7847f3 commit ba6bf71
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 61 deletions.
1 change: 1 addition & 0 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Code quality:
- Find an alternative to david-dm
- https://www.npmjs.com/package/standard#what-you-might-do-if-youre-clever
- rename master branch to main
- Keep support for CommonJS and ESM
Package:
✔ Update all dependencies @done(18-10-17 20:36)
✔ Rewite scripts @done(18-10-17 20:36)
Expand Down
16 changes: 15 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@
"lodash.flattendeep": "^4.4.0",
"lodash.isempty": "^4.4.0",
"lodash.negate": "^3.0.2",
"normalize-path": "^3.0.0"
"normalize-path": "^3.0.0",
"split2": "^4.1.0"
},
"optionalDependencies": {},
"devDependencies": {
"c8": "^7.11.0",
"chai": "^4.3.4",
Expand Down
88 changes: 44 additions & 44 deletions src/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,60 +29,60 @@ export const onStderrFactory = ({ Err }) => (stream, buffer) => {
return stream
}

export const onStdoutFactory = ({ Lines, Maybe }) => (stream, chunk) => {
const lines = Lines.fromBuffer(stream, chunk)
export const onStdoutFactory = ({ Maybe }) => (stream, chunk) => {
const line = chunk //thanks to split2

// Maybe functions check if a condition is true and run the corresponding
// actions. They can mutate the stream, emit events, etc. The structure bellow
// only does flow control.
for (const line of lines) {
debug('stdout: %s', line)
// for (const line of lines) {
debug('stdout: %s', line)

// Infos about the opertation are given by 7z on the stdout. They can be:
// - colon-seprated: `Creating archive: DirNew/BaseExt.7z`
// - equal-separated: `Method = LZMA2:12`
// - two on one line: `Prop 1: Data 1, # Prop 2: Data 2`
// - in the HEADERS or in the FOOTERS
// stream function match if the current line contains some infos. A **Map**
// is used to store infos in the stream.
const infos = Maybe.info(stream, line)
if (infos) {
continue // at next line
}

// End of HEADERS can be easy to detected with list and hash commands that
// outputs a `---- -- ----` line, but in symbol commands the end of HEADERS
// can only be detected when the line match a BODY data: In such cases the
// loop has to continue in order to properly porcess the BODY data.
const endOfHeaders = Maybe.endOfHeaders(stream, line)
if (endOfHeaders && stream._dataType !== 'symbol') {
continue // at next line
}
// Infos about the opertation are given by 7z on the stdout. They can be:
// - colon-seprated: `Creating archive: DirNew/BaseExt.7z`
// - equal-separated: `Method = LZMA2:12`
// - two on one line: `Prop 1: Data 1, # Prop 2: Data 2`
// - in the HEADERS or in the FOOTERS
// stream function match if the current line contains some infos. A **Map**
// is used to store infos in the stream.
const infos = Maybe.info(stream, line)
if (infos) {
return stream // at next line
}

// Optimization: Continue to the next line. At this point if the stream is
// in stage BODY all data carried by the current line has been processed.
const stageBody = (stream._stage === STAGE_BODY)
if (!stageBody) {
continue // at next line
}
// End of HEADERS can be easy to detected with list and hash commands that
// outputs a `---- -- ----` line, but in symbol commands the end of HEADERS
// can only be detected when the line match a BODY data: In such cases the
// loop has to continue in order to properly porcess the BODY data.
const endOfHeaders = Maybe.endOfHeaders(stream, line)
if (endOfHeaders && stream._dataType !== 'symbol') {
return stream // at next line
}

const endOfBody = Maybe.endOfBody(stream, line)
if (endOfBody) {
continue // at next line
}
// Optimization: Continue to the next line. At this point if the stream is
// in stage BODY all data carried by the current line has been processed.
const stageBody = (stream._stage === STAGE_BODY)
if (!stageBody) {
return stream // at next line
}

// Progress as a percentage is only displayed to stdout when the `-bsp1`
// switch is specified. Progress can has several forms:
// - only percent: ` 0%`
// - with file count: ` 23% 4`
// - with file name: ` 23% 4 file.txt`
const bodyProgress = Maybe.progress(stream, line)
if (bodyProgress) {
continue // at next line
}
const endOfBody = Maybe.endOfBody(stream, line)
if (endOfBody) {
return stream // at next line
}

Maybe.bodyData(stream, line)
// Progress as a percentage is only displayed to stdout when the `-bsp1`
// switch is specified. Progress can has several forms:
// - only percent: ` 0%`
// - with file count: ` 23% 4`
// - with file name: ` 23% 4 file.txt`
const bodyProgress = Maybe.progress(stream, line)
if (bodyProgress) {
return stream // at next line
}

Maybe.bodyData(stream, line)
// }
return stream
}

Expand Down
7 changes: 5 additions & 2 deletions src/lifecycle.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import libdebug from 'debug'
import split2 from 'split2'
import { spawn } from 'child_process'
import { Readable } from 'stream'
import { STAGE_HEADERS } from './references.js'
Expand Down Expand Up @@ -60,9 +61,10 @@ export const listenFactory = ({
stderrHandler,
endHandler
}) => stream => {
debug('lifecycle: listen')
stream._childProcess.on('error', err => errorHandler(stream, err))
stream._childProcess.stderr.on('data', chunk => stderrHandler(stream, chunk))
stream._childProcess.stdout.on('data', chunk => stdoutHandler(stream, chunk))
stream._childProcess.stderr.pipe(split2()).on('data', chunk => stderrHandler(stream, chunk))
stream._childProcess.stdout.pipe(split2()).on('data', chunk => stdoutHandler(stream, chunk))
stream._childProcess.on('close', () => endHandler(stream))
return stream
}
Expand All @@ -72,6 +74,7 @@ export const run = stream => {
detached: true,
windowsHide: true
}, stream._spawnOptions)
debug('lifecycle: spawn', stream._bin, stream._args, spawnOptions)
stream._childProcess = spawn(stream._bin, stream._args, spawnOptions)
return stream
}
Expand Down
11 changes: 4 additions & 7 deletions src/lines.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ import { LINE_SPLIT } from './regexp.js'
// When 7zip writes a progress value to stdout a new line is not created:
// Instead 7zip uses combination on backpaces and spaces char.
export const fromBuffer = (seven, buffer) => {
// if (seven._lastLinePartial) {
// buffer = Buffer.concat([seven._lastLinePartial, buffer])
// }
// const lines = buffer.toString().split(LINE_SPLIT)
if (seven._lastLinePartial) {
buffer = Buffer.concat([seven._lastLinePartial, buffer])
}
const lines = buffer.toString().split(LINE_SPLIT)
// const offset = buffer.lastIndexOf('\n') + 1
// const newLastLine = buffer.slice(offset)
// const isNewLastLineComplete = (newLastLine.indexOf('\n') === newLastLine.length - 1)
Expand All @@ -35,9 +35,6 @@ export const fromBuffer = (seven, buffer) => {
// } else {
// delete seven._lastLinePartial
// }
// return lines
const lines = buffer.toString().split(LINE_SPLIT)
// console.log(lines)
return lines
}

Expand Down
8 changes: 4 additions & 4 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,23 @@ import Flags from './flags.js'
import Parser from './parser.js'
import { onErrorFactory, onStderrFactory, onStdoutFactory, onEndFactory } from './events.js'
import Err from './error.js'
import Lines from './lines.js'
// import Lines from './lines.js'
import Maybe from './maybe.js'
import Commands from './commands.js'

// Expose the listen function to the API so a user can listen to a sdtio stream
// non emitted by the current (ie. in the run() function).
const listenFactory = ({ Lifecycle, Err, Lines, Maybe }) => seven => {
const listenFactory = ({ Lifecycle, Err, Maybe }) => seven => {
Lifecycle.listenFactory({
errorHandler: onErrorFactory({ Err }),
stderrHandler: onStderrFactory({ Err }),
stdoutHandler: onStdoutFactory({ Lines, Maybe }),
stdoutHandler: onStdoutFactory({ Maybe }),
endHandler: onEndFactory()
})(seven)
return seven
}

const listen = listenFactory({ Lifecycle, Err, Lines, Maybe })
const listen = listenFactory({ Lifecycle, Err, Maybe })

// Function responsable for creating the streams using. Advanced usage of
// $childProcess and $defer is done at this stage.
Expand Down
3 changes: 2 additions & 1 deletion test/unit/lines.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { expect } from 'chai'
import { fromBuffer } from '../../src/lines.js'

describe('Unit: lines.js', function () {
describe.skip('Unit: lines.js', function () {
describe('toLinesFactory()', function () {
it('should return simple values from 1-line', function () {
const seven = {}
Expand All @@ -20,6 +20,7 @@ describe('Unit: lines.js', function () {
const buffer2 = Buffer.from(' line\n')
const r2 = fromBuffer(seven, buffer2)
expect(r2).to.includes('second line')
console.log(r1, r2)
})

it('should work on Windows stdout', function () {
Expand Down

0 comments on commit ba6bf71

Please sign in to comment.