Skip to content

Commit

Permalink
feat: add large file rules
Browse files Browse the repository at this point in the history
  • Loading branch information
Neil Zhao committed Sep 26, 2022
1 parent 29044cd commit 2e48a85
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 0 deletions.
13 changes: 13 additions & 0 deletions rules/large-file-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"type": "object",
"properties": {
"globsAll": {
"type": "array",
"items": { "type": "number" }
},
"size": {"type": "number"}
},
"required": ["content"],
"oneOf": [{ "required": ["globsAll"] }, { "required": ["files"] }]
}
69 changes: 69 additions & 0 deletions rules/large-file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
const nodefs = require('fs')
// eslint-disable-next-line no-unused-vars
const Result = require('../lib/result')
// eslint-disable-next-line no-unused-vars
const path = require('path')
/**
* Check if a list of files is larger than provided file system size.
*
* @param {FileSystem} fs A filesystem object configured with filter paths and target directories
* @param {object} options The rule configuration
* @param {boolean} not Whether or not to invert the result (not contents instead of contents)
* @returns {Promise<Result>} The lint rule result
*/
async function largeFile(fs, options, not = false) {
// support legacy configuration keys
const fileList = options.globsAll || options.files
const files = await fs.findAllFiles(fileList, !!options.nocase)

if (files.length === 0) {
return new Result(
'Did not find file matching the specified patterns',
fileList.map(f => {
return { passed: false, pattern: f }
}),
!options['fail-on-non-existent']
)
}

const results = (
await Promise.all(
files.map(async file => {
const filePath = path.resolve(fs.targetDir, file)
const stat = await nodefs.promises.stat(filePath)
const passed = stat.size < options.size
const readerFriendlySize =
stat.size > 1000 * 1000
? `${stat.size / 1000000} MB`
: `${stat.size / 1000} KB`
const message = `File size ${readerFriendlySize} bytes`

return {
passed: not ? !passed : passed,
path: filePath,
message,
size: stat.size
}
})
)
)
.filter(fileStat => {
return !fileStat.passed
})
.sort((stat1, stat2) => {
return stat2.size - stat1.size
})

const filteredResults = results.filter(r => r !== null)
const passed = !filteredResults.find(r => !r.passed)
if (passed.length === 0 || passed) {
return new Result(
`No file larger than ${options.size} bytes found.`,
filteredResults,
passed
)
}
return new Result('', filteredResults, passed)
}

module.exports = largeFile
36 changes: 36 additions & 0 deletions tests/rules/large_file_tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2022 TODO Group. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

const chai = require('chai')
const expect = chai.expect
const FileSystem = require('../../lib/file_system')

describe('rule', () => {
describe('largeFile', () => {
const largeFile = require('../../rules/large-file')

it('returns a passed result if file is smaller than threshold size.', async () => {
const ruleOptions = {
// file size ~41KB
globsAll: ['tests/rules/image_for_test.png'],
size: 42000
}

const actual = await largeFile(new FileSystem(), ruleOptions)

expect(actual.passed).to.equal(true)
})

it('returns a failure result if file is larger than threshold size.', async () => {
const ruleOptions = {
// file size ~41KB
globsAll: ['tests/rules/image_for_test.png'],
size: 40000
}

const actual = await largeFile(new FileSystem(), ruleOptions)

expect(actual.passed).to.equal(false)
})
})
})

0 comments on commit 2e48a85

Please sign in to comment.