feat: Print folder sizes with cypress cache list command. (#8590)

This commit is contained in:
Kukhyeon Heo
2020-10-06 00:31:59 +09:00
committed by GitHub
parent 4d76049d2c
commit aa4772c4cf
7 changed files with 147 additions and 6 deletions

View File

@@ -55,3 +55,13 @@ exports['cache list with warn log level'] = `
│ 2.3.4 │ unknown │
└─────────┴───────────┘
`
exports['lib/tasks/cache .list shows sizes 1'] = `
┌─────────┬──────────────┬───────┐
│ version │ last used │ size │
├─────────┼──────────────┼───────┤
│ 1.2.3 │ 3 months ago │ 0.2MB │
├─────────┼──────────────┼───────┤
│ 2.3.4 │ unknown │ 0.2MB │
└─────────┴──────────────┴───────┘
`

View File

@@ -112,6 +112,8 @@ exports['cli unknown option shows help for cache command - unknown option --foo
list list cached binary versions
path print the path to the binary cache
clear delete all cached binaries
--size Used with the list command to show the sizes of the cached
folders
-h, --help output usage information
-------
stderr:
@@ -142,6 +144,8 @@ exports['cli unknown option shows help for cache command - unknown sub-command f
list list cached binary versions
path print the path to the binary cache
clear delete all cached binaries
--size Used with the list command to show the sizes of the cached
folders
-h, --help output usage information
-------
stderr:
@@ -170,6 +174,8 @@ exports['cli unknown option shows help for cache command - no sub-command 1'] =
list list cached binary versions
path print the path to the binary cache
clear delete all cached binaries
--size Used with the list command to show the sizes of the cached
folders
-h, --help output usage information
-------
stderr:

View File

@@ -102,6 +102,7 @@ const descriptions = {
cacheClear: 'delete all cached binaries',
cacheList: 'list cached binary versions',
cachePath: 'print the path to the binary cache',
cacheSize: 'Used with the list command to show the sizes of the cached folders',
ciBuildId: 'the unique identifier for a run on your CI provider. typically a "BUILD_ID" env var. this value is automatically detected for most CI providers',
config: 'sets configuration values. separate multiple values with a comma. overrides any value in cypress.json.',
configFile: 'path to JSON file where configuration values are set. defaults to "cypress.json". pass "false" to disable.',
@@ -386,6 +387,7 @@ module.exports = {
.option('list', text('cacheList'))
.option('path', text('cachePath'))
.option('clear', text('cacheClear'))
.option('--size', text('cacheSize'))
.action(function (opts, args) {
if (!args || !args.length) {
this.outputHelp()
@@ -398,6 +400,12 @@ module.exports = {
unknownOption.call(this, `cache ${command}`, 'command')
}
if (command === 'list') {
cache.list(opts.size)
return
}
cache[command]()
})

View File

@@ -7,12 +7,14 @@ const Table = require('cli-table3')
const moment = require('moment')
const chalk = require('chalk')
const _ = require('lodash')
const getFolderSize = require('./get-folder-size')
// output colors for the table
const colors = {
titles: chalk.white,
dates: chalk.cyan,
values: chalk.green,
size: chalk.gray,
}
const logCachePath = () => {
@@ -25,29 +27,46 @@ const clear = () => {
return fs.removeAsync(state.getCacheDir())
}
const fileSizeInMB = (size) => {
return `${(size / 1024 / 1024).toFixed(1)}MB`
}
/**
* Collects all cached versions, finds when each was used
* and prints a table with results to the terminal
*/
const list = () => {
return getCachedVersions()
const list = (showSize) => {
return getCachedVersions(showSize)
.then((binaries) => {
const head = [colors.titles('version'), colors.titles('last used')]
if (showSize) {
head.push(colors.titles('size'))
}
const table = new Table({
head: [colors.titles('version'), colors.titles('last used')],
head,
})
binaries.forEach((binary) => {
const versionString = colors.values(binary.version)
const lastUsed = binary.accessed ? colors.dates(binary.accessed) : 'unknown'
const row = [versionString, lastUsed]
return table.push([versionString, lastUsed])
if (showSize) {
const size = colors.size(fileSizeInMB(binary.size))
row.push(size)
}
return table.push(row)
})
logger.always(table.toString())
})
}
const getCachedVersions = () => {
const getCachedVersions = (showSize) => {
const cacheDir = state.getCacheDir()
return fs
@@ -84,6 +103,20 @@ const getCachedVersions = () => {
return binary
})
})
.mapSeries((binary) => {
if (showSize) {
const binaryDir = state.getBinaryDir(binary.version)
return getFolderSize(binaryDir).then((size) => {
return {
...binary,
size,
}
})
}
return binary
})
}
module.exports = {

View File

@@ -0,0 +1,36 @@
const fs = require('../fs')
const { join } = require('path')
const Bluebird = require('bluebird')
/**
* Get the size of a folder or a file.
*
* This function returns the actual file size of the folder (size), not the allocated space on disk (size on disk).
* For more details between the difference, check this link:
* https://www.howtogeek.com/180369/why-is-there-a-big-difference-between-size-and-size-on-disk/
*
* @param {string} path path to the file or the folder.
*/
async function getSize (path) {
const stat = await fs.lstat(path)
if (stat.isDirectory()) {
const list = await fs.readdir(path)
return Bluebird.resolve(list).reduce(async (prev, curr) => {
const currPath = join(path, curr)
const s = await fs.lstat(currPath)
if (s.isDirectory()) {
return prev + await getSize(currPath)
}
return prev + s.size
}, 0)
}
return stat.size
}
module.exports = getSize

View File

@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<style>
body {
font-family: "Courier New", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #000;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier New", Courier, monospace;
}
</style>
</head>
<body><pre>┌─────────┬──────────────┬───────┐
<span style="color:#AAA">version<span style="color:#eee"><span style="color:#AAA">last used<span style="color:#eee"><span style="color:#AAA">size<span style="color:#eee">
├─────────┼──────────────┼───────┤
<span style="color:#0A0">1.2.3<span style="color:#eee"><span style="color:#0AA">3 months ago<span style="color:#eee"><span style="color:#555">0.2MB<span style="color:#eee">
├─────────┼──────────────┼───────┤
<span style="color:#0A0">2.3.4<span style="color:#eee"> │ unknown │ <span style="color:#555">0.2MB<span style="color:#eee">
└─────────┴──────────────┴───────┘</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>

View File

@@ -20,7 +20,12 @@ describe('lib/tasks/cache', () => {
mockfs({
'/.cache/Cypress': {
'1.2.3': {
'Cypress': {},
'Cypress': {
'file1': Buffer.from(new Array(32 * 1024).fill(1)),
'dir': {
'file2': Buffer.from(new Array(128 * 1042).fill(2)),
},
},
},
'2.3.4': {
'Cypress.app': {},
@@ -204,5 +209,21 @@ describe('lib/tasks/cache', () => {
await cache.list()
await snapshotWithHtml('second-binary-never-used.html')
})
it('shows sizes', async function () {
sinon.stub(state, 'getPathToExecutable').returns('/.cache/Cypress/1.2.3/app/cypress')
const statAsync = sinon.stub(fs, 'statAsync')
statAsync.onFirstCall().resolves({
atime: moment().subtract(3, 'month').valueOf(),
})
// the second binary has never been accessed
statAsync.onSecondCall().resolves()
await cache.list(true)
await snapshotWithHtml('show-size.html')
})
})
})