Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ ${binPathEnvVar}="\$DIR/${bin}" ${redirectedEnvVar}=1 "$DIR/../${version}/bin/${

await Promise.all(
files
.filter((f) => isNotSpecial(this.config.version, f.path) && isOld(f.stat))
.filter((f) => isNotSpecial(f.path, this.config.version) && isOld(f.stat))
.map((f) => rm(f.path, {force: true, recursive: true})),
)
} catch (error: unknown) {
Expand Down
93 changes: 92 additions & 1 deletion test/update.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {expect} from 'chai'
import {got} from 'got'
import nock from 'nock'
import {existsSync} from 'node:fs'
import {mkdir, rm, symlink, writeFile} from 'node:fs/promises'
import {mkdir, rm, symlink, utimes, writeFile} from 'node:fs/promises'
import path from 'node:path'
import zlib from 'node:zlib'
import sinon from 'sinon'
Expand Down Expand Up @@ -42,6 +42,33 @@ function initUpdater(config: Config): Updater {
return updater
}

const setOldMtime = async (filePath: string): Promise<void> => {
const oldDate = new Date()
oldDate.setDate(oldDate.getDate() - 43)
await utimes(filePath, oldDate, oldDate)
}

const setupTidyClientRoot = async (config: Interfaces.Config): Promise<string> => {
const root = config.scopedEnvVar('OCLIF_CLIENT_HOME') || path.join(config.dataDir, 'client')
await mkdir(root, {recursive: true})

// Create current version directory (matches config.version = '2.0.0')
const versionDir = path.join(root, '2.0.0')
await mkdir(path.join(versionDir, 'bin'), {recursive: true})
await writeFile(path.join(versionDir, 'bin', config.bin), 'binary', 'utf8')

// Create bin/ directory with launcher script
await mkdir(path.join(root, 'bin'), {recursive: true})
await writeFile(path.join(root, 'bin', config.bin), '../2.0.0/bin', 'utf8')

// Create current symlink
if (!existsSync(path.join(root, 'current'))) {
await symlink(path.join(root, '2.0.0'), path.join(root, 'current'))
}

return root
}

describe('update plugin', () => {
let config: Config
let updater: Updater
Expand Down Expand Up @@ -298,4 +325,68 @@ describe('update plugin', () => {
const stdout = stripAnsi(collector.stdout.join(' '))
expect(stdout).to.matches(/Updating to a specific version will not update the channel/)
})

describe('tidy', () => {
it('should preserve bin, current, and active version directories during tidy', async () => {
clientRoot = await setupTidyClientRoot(config)

// Create old version directory that should be cleaned up
const oldVersionDir = path.join(clientRoot, '1.0.0-abc1234')
await mkdir(path.join(oldVersionDir, 'bin'), {recursive: true})
await writeFile(path.join(oldVersionDir, 'bin', 'example-cli'), 'old version', 'utf8')

// Backdate the old version directory to be older than 42 days
await setOldMtime(oldVersionDir)

// Also backdate bin/ and current to verify they are preserved even when old
await setOldMtime(path.join(clientRoot, 'bin'))
await setOldMtime(path.join(clientRoot, 'current'))

// Backdate the active version directory too - it should still be preserved
await setOldMtime(path.join(clientRoot, '2.0.0'))

// Trigger tidy via runUpdate (already on same version, but tidy still runs)
const manifestRegex = new RegExp(
`channels\\/stable\\/example-cli-${config.platform}-${config.arch}-buildmanifest`,
)
nock(/oclif-staging.s3.amazonaws.com/)
.get(manifestRegex)
.reply(200, {version: '2.0.0'})

updater = initUpdater(config)
await updater.runUpdate({autoUpdate: false})

// Verify bin/ and current survived even though they are old
expect(existsSync(path.join(clientRoot, 'bin'))).to.be.true
expect(existsSync(path.join(clientRoot, 'current'))).to.be.true

// Verify active version directory survived even though it is old
expect(existsSync(path.join(clientRoot, '2.0.0'))).to.be.true

// Verify old version was cleaned up
expect(existsSync(oldVersionDir)).to.be.false
})

it('should not delete entries newer than 42 days', async () => {
clientRoot = await setupTidyClientRoot(config)

// Create a recent version directory (should survive)
const recentVersionDir = path.join(clientRoot, '1.9.0-def5678')
await mkdir(path.join(recentVersionDir, 'bin'), {recursive: true})
await writeFile(path.join(recentVersionDir, 'bin', 'example-cli'), 'recent version', 'utf8')

const manifestRegex = new RegExp(
`channels\\/stable\\/example-cli-${config.platform}-${config.arch}-buildmanifest`,
)
nock(/oclif-staging.s3.amazonaws.com/)
.get(manifestRegex)
.reply(200, {version: '2.0.0'})

updater = initUpdater(config)
await updater.runUpdate({autoUpdate: false})

// Recent version should survive
expect(existsSync(recentVersionDir)).to.be.true
})
})
})
Loading