feat: save the pnpm state file to a state directory (#3580)

ref #2574
This commit is contained in:
Zoltan Kochan
2021-07-05 02:31:08 +03:00
committed by GitHub
parent 691f647137
commit 5aaf3e3fa1
9 changed files with 115 additions and 65 deletions

View File

@@ -0,0 +1,5 @@
---
"@pnpm/config": minor
---
New setting added: stateDir.

View File

@@ -90,6 +90,7 @@ export interface Config {
// pnpm specific configs
cacheDir: string
stateDir: string
storeDir?: string
virtualStoreDir?: string
verifyStoreIntegrity?: boolean

View File

@@ -0,0 +1,38 @@
import os from 'os'
import path from 'path'
export function getCacheDir (
opts: {
env: NodeJS.ProcessEnv
platform: string
}
) {
if (opts.env.XDG_CACHE_HOME) {
return path.join(opts.env.XDG_CACHE_HOME, 'pnpm')
}
if (opts.platform !== 'win32') {
return path.join(os.homedir(), '.cache/pnpm')
}
if (opts.env.LOCALAPPDATA) {
return path.join(opts.env.LOCALAPPDATA, 'pnpm-cache')
}
return path.join(os.homedir(), '.pnpm-cache')
}
export function getStateDir (
opts: {
env: NodeJS.ProcessEnv
platform: string
}
) {
if (opts.env.XDG_STATE_HOME) {
return path.join(opts.env.XDG_STATE_HOME, 'pnpm')
}
if (opts.platform !== 'win32') {
return path.join(os.homedir(), '.local/state/pnpm')
}
if (opts.env.LOCALAPPDATA) {
return path.join(opts.env.LOCALAPPDATA, 'pnpm-state')
}
return path.join(os.homedir(), '.pnpm-state')
}

View File

@@ -1,20 +0,0 @@
import os from 'os'
import path from 'path'
export default function getCacheDir (
opts: {
env: NodeJS.ProcessEnv
platform: string
}
) {
if (opts.env.XDG_CACHE_HOME) {
return path.join(opts.env.XDG_CACHE_HOME, 'pnpm')
}
if (opts.platform !== 'win32') {
return path.join(os.homedir(), '.cache/pnpm')
}
if (opts.env.LOCALAPPDATA) {
return path.join(opts.env.LOCALAPPDATA, 'pnpm-cache')
}
return path.join(os.homedir(), '.pnpm-cache')
}

View File

@@ -13,7 +13,7 @@ import realpathMissing from 'realpath-missing'
import whichcb from 'which'
import getScopeRegistries, { normalizeRegistry } from './getScopeRegistries'
import findBestGlobalPrefix from './findBestGlobalPrefix'
import getCacheDir from './getCacheDir'
import { getCacheDir, getStateDir } from './dirs'
import {
Config,
ConfigWithDeprecatedSettings,
@@ -362,6 +362,9 @@ export default async (
if (!pnpmConfig.cacheDir) {
pnpmConfig.cacheDir = getCacheDir(process)
}
if (!pnpmConfig.stateDir) {
pnpmConfig.stateDir = getStateDir(process)
}
if (pnpmConfig['hoist'] === false) {
delete pnpmConfig.hoistPattern
}

View File

@@ -0,0 +1,49 @@
import os from 'os'
import path from 'path'
import { getCacheDir, getStateDir } from '../lib/dirs'
test('getCacheDir()', () => {
expect(getCacheDir({
env: {
XDG_CACHE_HOME: '/home/foo/cache',
},
platform: 'linux',
})).toBe(path.join('/home/foo/cache', 'pnpm'))
expect(getCacheDir({
env: {},
platform: 'linux',
})).toBe(path.join(os.homedir(), '.cache/pnpm'))
expect(getCacheDir({
env: {
LOCALAPPDATA: '/localappdata',
},
platform: 'win32',
})).toBe(path.join('/localappdata', 'pnpm-cache'))
expect(getCacheDir({
env: {},
platform: 'win32',
})).toBe(path.join(os.homedir(), '.pnpm-cache'))
})
test('getStateDir()', () => {
expect(getStateDir({
env: {
XDG_STATE_HOME: '/home/foo/state',
},
platform: 'linux',
})).toBe(path.join('/home/foo/state', 'pnpm'))
expect(getStateDir({
env: {},
platform: 'linux',
})).toBe(path.join(os.homedir(), '.local/state/pnpm'))
expect(getStateDir({
env: {
LOCALAPPDATA: '/localappdata',
},
platform: 'win32',
})).toBe(path.join('/localappdata', 'pnpm-state'))
expect(getStateDir({
env: {},
platform: 'win32',
})).toBe(path.join(os.homedir(), '.pnpm-state'))
})

View File

@@ -1,26 +0,0 @@
import os from 'os'
import path from 'path'
import getCacheDir from '../lib/getCacheDir'
test('getCacheDir()', () => {
expect(getCacheDir({
env: {
XDG_CACHE_HOME: '/home/foo/cache',
},
platform: 'linux',
})).toBe(path.join('/home/foo/cache', 'pnpm'))
expect(getCacheDir({
env: {},
platform: 'linux',
})).toBe(path.join(os.homedir(), '.cache/pnpm'))
expect(getCacheDir({
env: {
LOCALAPPDATA: '/localappdata',
},
platform: 'win32',
})).toBe(path.join('/localappdata', 'pnpm-cache'))
expect(getCacheDir({
env: {},
platform: 'win32',
})).toBe(path.join(os.homedir(), '.pnpm-cache'))
})

View File

@@ -5,14 +5,6 @@ import loadJsonFile from 'load-json-file'
import writeJsonFile from 'write-json-file'
import checkForUpdates from './checkForUpdates'
jest.mock('os', () => {
const os = jest.requireActual('os')
return {
...os,
homedir: () => process.cwd(),
}
})
jest.mock('@pnpm/core-loggers', () => ({
updateCheckLogger: { debug: jest.fn() },
}))
@@ -31,14 +23,17 @@ test('check for updates when no pnpm state file is present', async () => {
version: '1.0.0',
},
})
await checkForUpdates(config)
await checkForUpdates({
...config,
stateDir: process.cwd(),
})
expect(updateCheckLogger.debug).toBeCalledWith({
currentVersion: expect.any(String),
latestVersion: expect.any(String),
})
const state = await loadJsonFile('.pnpm-state.json')
const state = await loadJsonFile('pnpm-state.json')
expect(state).toEqual({
lastUpdateCheck: expect.any(String),
})
@@ -48,7 +43,7 @@ test('do not check for updates when last update check happened recently', async
prepareEmpty()
const lastUpdateCheck = new Date().toUTCString()
await writeJsonFile('.pnpm-state.json', { lastUpdateCheck })
await writeJsonFile('pnpm-state.json', { lastUpdateCheck })
const { config } = await getConfig({
cliOptions: {},
@@ -57,11 +52,14 @@ test('do not check for updates when last update check happened recently', async
version: '1.0.0',
},
})
await checkForUpdates(config)
await checkForUpdates({
...config,
stateDir: process.cwd(),
})
expect(updateCheckLogger.debug).not.toBeCalled()
const state = await loadJsonFile('.pnpm-state.json')
const state = await loadJsonFile('pnpm-state.json')
expect(state).toStrictEqual({ lastUpdateCheck })
})
@@ -71,7 +69,7 @@ test('check for updates when last update check happened two days ago', async ()
const lastUpdateCheckDate = new Date()
lastUpdateCheckDate.setDate(lastUpdateCheckDate.getDate() - 2)
const initialLastUpdateCheck = lastUpdateCheckDate.toUTCString()
await writeJsonFile('.pnpm-state.json', {
await writeJsonFile('pnpm-state.json', {
lastUpdateCheck: initialLastUpdateCheck,
})
@@ -82,14 +80,17 @@ test('check for updates when last update check happened two days ago', async ()
version: '1.0.0',
},
})
await checkForUpdates(config)
await checkForUpdates({
...config,
stateDir: process.cwd(),
})
expect(updateCheckLogger.debug).toBeCalledWith({
currentVersion: expect.any(String),
latestVersion: expect.any(String),
})
const state = await loadJsonFile<{ lastUpdateCheck: string }>('.pnpm-state.json')
const state = await loadJsonFile<{ lastUpdateCheck: string }>('pnpm-state.json')
expect(state.lastUpdateCheck).toBeDefined()
expect(state.lastUpdateCheck).not.toEqual(initialLastUpdateCheck)
})

View File

@@ -1,4 +1,3 @@
import { homedir } from 'os'
import path from 'path'
import packageManager from '@pnpm/cli-meta'
import { Config } from '@pnpm/config'
@@ -15,7 +14,7 @@ interface State {
const UPDATE_CHECK_FREQUENCY = 24 * 60 * 60 * 1000 // 1 day
export default async function (config: Config) {
const stateFile = path.join(homedir(), '.pnpm-state.json')
const stateFile = path.join(config.stateDir, 'pnpm-state.json')
let state: State | undefined
try {
state = await loadJsonFile(stateFile)