Skip to content

Commit

Permalink
feat(saving): only save if the file contents were unchanged
Browse files Browse the repository at this point in the history
This should speed things up a bit and prevent enditors from flashing the
content when the save occurs (if it's not necessary anyway)
  • Loading branch information
Kent C. Dodds committed Jan 29, 2017
1 parent 3c94377 commit 33d3f9c
Show file tree
Hide file tree
Showing 6 changed files with 454 additions and 417 deletions.
6 changes: 6 additions & 0 deletions __mocks__/glob.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ module.exports = jest.fn(function mockGlob(globString, options, callback) {
callback(null, [])
} else if (globString.includes('throw-error')) {
callback(new Error('something weird happened'))
} else if (globString.includes('no-change')) {
callback(null, [
fredProject('no-change/1.js'),
fredProject('no-change/2.js'),
fredProject('no-change/3.js'),
])
} else {
throw new Error(
`Your test globString: "${globString}"` +
Expand Down
2 changes: 2 additions & 0 deletions __mocks__/prettier-eslint.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
const format = jest.fn(({text, filePath = ''}) => {
if (text === 'MOCK_SYNTAX_ERROR' || filePath.includes('syntax-error')) {
throw new Error('Mock error for a syntax error')
} else if (filePath.includes('no-change')) {
return text
}
return `MOCK_OUTPUT for ${filePath || 'stdin'}`
})
Expand Down
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"find-up": "^2.1.0",
"get-stdin": "^5.0.1",
"glob": "^7.1.1",
"prettier-eslint": "^2.3.3",
"prettier-eslint": "^3.0.0",
"rxjs": "^5.0.3",
"yargs": "^6.6.0"
},
Expand All @@ -41,7 +41,7 @@
"cz-conventional-changelog": "^1.2.0",
"eslint": "^3.10.2",
"eslint-config-kentcdodds": "^11.1.0",
"husky": "^0.12.0",
"husky": "^0.13.1",
"jest-cli": "^18.1.0",
"opt-cli": "^1.5.1",
"p-s": "^3.0.3",
Expand All @@ -59,7 +59,10 @@
"kentcdodds/jest"
],
"rules": {
"max-len": [2, 80]
"max-len": [
2,
80
]
}
},
"jest": {
Expand Down
17 changes: 14 additions & 3 deletions src/format-files.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ async function formatFilesFromGlobs(
return new Promise(resolve => {
const successes = []
const failures = []
const unchanged = []
Rx.Observable
.from(fileGlobs)
.mergeMap(getFilesFromGlob, null, concurrentGlobs)
Expand All @@ -77,6 +78,8 @@ async function formatFilesFromGlobs(
function onNext(info) {
if (info.error) {
failures.push(info)
} else if (info.unchanged) {
unchanged.push(info)
} else {
successes.push(info)
}
Expand Down Expand Up @@ -105,6 +108,10 @@ async function formatFilesFromGlobs(
`${failure} formatting ${count} files with prettier-eslint`,
)
}
if (unchanged.length) {
const count = chalk.bold(unchanged.length)
console.log(`${count} files were ${chalk.gray('unchanged')}`)
}
resolve({successes, failures})
}
})
Expand All @@ -129,9 +136,13 @@ function formatFile(filePath, prettierESLintOptions, cliOptions) {
})

if (cliOptions.write) {
format$ = format$.mergeMap(
info => rxWriteFile(filePath, info.formatted).map(() => fileInfo),
)
format$ = format$.mergeMap(info => {
if (info.text === info.formatted) {
return Rx.Observable.of(Object.assign(fileInfo, {unchanged: true}))
} else {
return rxWriteFile(filePath, info.formatted).map(() => fileInfo)
}
})
} else {
format$ = format$.map(info => {
console.log(info.formatted)
Expand Down
19 changes: 13 additions & 6 deletions src/format-files.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ beforeEach(() => {
console.error = jest.fn()
formatMock.mockClear()
fsMock.writeFile.mockClear()
fsMock.readFile.mockClear()
})

test('sanity test', async () => {
Expand Down Expand Up @@ -55,12 +56,9 @@ test('should accept stdin', async () => {
mockGetStdin.stdin = ' var [ foo, { bar } ] = window.APP ;'
await formatFiles({stdin: true})
expect(formatMock).toHaveBeenCalledTimes(1)
expect(formatMock).toHaveBeenCalledWith(
expect.objectContaining({
// the trim is part of the test
text: mockGetStdin.stdin.trim(),
}),
)
// the trim is part of the test
const text = mockGetStdin.stdin.trim()
expect(formatMock).toHaveBeenCalledWith(expect.objectContaining({text}))
expect(console.log).toHaveBeenCalledTimes(1)
expect(console.log).toHaveBeenCalledWith('MOCK_OUTPUT for stdin')
})
Expand Down Expand Up @@ -108,3 +106,12 @@ test('forwards sillyLogs onto prettier-eslint', async () => {
const options = expect.objectContaining({sillyLogs: true})
expect(formatMock).toHaveBeenCalledWith(options)
})

test('wont save file if contents did not change', async () => {
const fileGlob = 'no-change/*.js'
await formatFiles({_: [fileGlob], write: true})
expect(fsMock.readFile).toHaveBeenCalledTimes(3)
expect(fsMock.writeFile).toHaveBeenCalledTimes(0)
const unchangedOutput = expect.stringMatching(/3.*?files.*?unchanged/)
expect(console.log).toHaveBeenCalledWith(unchangedOutput)
})
Loading

0 comments on commit 33d3f9c

Please sign in to comment.