Files
cypress/cli/lib/tasks/cache.js
2021-01-26 13:49:21 +06:30

163 lines
3.7 KiB
JavaScript

const state = require('./state')
const logger = require('../logger')
const fs = require('../fs')
const util = require('../util')
const { join } = require('path')
const Table = require('cli-table3')
const dayjs = require('dayjs')
const relativeTime = require('dayjs/plugin/relativeTime')
const chalk = require('chalk')
const _ = require('lodash')
const getFolderSize = require('./get-folder-size')
const Bluebird = require('bluebird')
dayjs.extend(relativeTime)
// output colors for the table
const colors = {
titles: chalk.white,
dates: chalk.cyan,
values: chalk.green,
size: chalk.gray,
}
const logCachePath = () => {
logger.always(state.getCacheDir())
return undefined
}
const clear = () => {
return fs.removeAsync(state.getCacheDir())
}
const prune = () => {
const cacheDir = state.getCacheDir()
const currentVersion = util.pkgVersion()
let deletedBinary = false
return fs.readdirAsync(cacheDir)
.then((versions) => {
return Bluebird.all(versions.map((version) => {
if (version !== currentVersion) {
deletedBinary = true
const versionDir = join(cacheDir, version)
return fs.removeAsync(versionDir)
}
}))
})
.then(() => {
if (deletedBinary) {
logger.always(`Deleted all binary caches except for the ${currentVersion} binary cache.`)
} else {
logger.always(`No binary caches found to prune.`)
}
})
.catch({ code: 'ENOENT' }, () => {
logger.always(`No Cypress cache was found at ${cacheDir}. Nothing to prune.`)
})
}
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 = (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,
})
binaries.forEach((binary) => {
const versionString = colors.values(binary.version)
const lastUsed = binary.accessed ? colors.dates(binary.accessed) : 'unknown'
const row = [versionString, lastUsed]
if (showSize) {
const size = colors.size(fileSizeInMB(binary.size))
row.push(size)
}
return table.push(row)
})
logger.always(table.toString())
})
}
const getCachedVersions = (showSize) => {
const cacheDir = state.getCacheDir()
return fs
.readdirAsync(cacheDir)
.filter(util.isSemver)
.map((version) => {
return {
version,
folderPath: join(cacheDir, version),
}
})
.mapSeries((binary) => {
// last access time on the folder is different from last access time
// on the Cypress binary
const binaryDir = state.getBinaryDir(binary.version)
const executable = state.getPathToExecutable(binaryDir)
return fs.statAsync(executable).then((stat) => {
const lastAccessedTime = _.get(stat, 'atime')
if (!lastAccessedTime) {
// the test runner has never been opened
// or could be a test simulating missing timestamp
return binary
}
const accessed = dayjs(lastAccessedTime).fromNow()
binary.accessed = accessed
return binary
}, (e) => {
// could not find the binary or gets its stats
return binary
})
})
.mapSeries((binary) => {
if (showSize) {
const binaryDir = state.getBinaryDir(binary.version)
return getFolderSize(binaryDir).then((size) => {
return {
...binary,
size,
}
})
}
return binary
})
}
module.exports = {
path: logCachePath,
clear,
prune,
list,
getCachedVersions,
}