Skip to content

Commit

Permalink
feat: do not alter file ownership
Browse files Browse the repository at this point in the history
BREAKING CHANGE: this package no longer attempts to change file ownership automatically
  • Loading branch information
nlf committed Oct 17, 2022
1 parent 32336f6 commit 849ef58
Show file tree
Hide file tree
Showing 14 changed files with 104 additions and 127 deletions.
3 changes: 0 additions & 3 deletions package-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -13778,8 +13778,6 @@
"json-parse-even-better-errors": "^2.3.1",
"json-stringify-nice": "^1.1.4",
"minimatch": "^5.1.0",
"mkdirp": "^1.0.4",
"mkdirp-infer-owner": "^2.0.0",
"nopt": "^6.0.0",
"npm-install-checks": "^5.0.0",
"npm-package-arg": "^9.0.0",
Expand All @@ -13793,7 +13791,6 @@
"promise-call-limit": "^1.0.1",
"read-package-json-fast": "^2.0.2",
"readdir-scoped-modules": "^1.1.0",
"rimraf": "^3.0.2",
"semver": "^7.3.7",
"ssri": "^9.0.0",
"treeverse": "^2.0.0",
Expand Down
3 changes: 1 addition & 2 deletions workspaces/arborist/bin/lib/logging.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const log = require('proc-log')
const mkdirp = require('mkdirp')
const fs = require('fs')
const { dirname } = require('path')
const os = require('os')
Expand Down Expand Up @@ -70,7 +69,7 @@ if (options.loglevel !== 'silent') {

if (options.logfile) {
log.silly('logfile', options.logfile)
mkdirp.sync(dirname(options.logfile))
fs.mkdirSync(dirname(options.logfile), { recursive: true })
const fd = fs.openSync(options.logfile, 'a')
addLogListener((str) => fs.writeSync(fd, str))
}
Expand Down
2 changes: 1 addition & 1 deletion workspaces/arborist/docs/reify.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ Fail: rename each retired `.${name}-hash` folder back to `${name}`

### step 2: create sparse tree

Now that the shallowest changing nodes are retired, `mkdirp` all leaf
Now that the shallowest changing nodes are retired, `mkdir` all leaf
nodes.

```
Expand Down
4 changes: 1 addition & 3 deletions workspaces/arborist/lib/arborist/build-ideal-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ const { resolve, dirname } = require('path')
const { promisify } = require('util')
const treeCheck = require('../tree-check.js')
const readdir = promisify(require('readdir-scoped-modules'))
const fs = require('fs')
const lstat = promisify(fs.lstat)
const readlink = promisify(fs.readlink)
const { lstat, readlink } = require('fs/promises')
const { depth } = require('treeverse')
const log = require('proc-log')

Expand Down
42 changes: 21 additions & 21 deletions workspaces/arborist/lib/arborist/reify.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,13 @@ const log = require('proc-log')

const { dirname, resolve, relative } = require('path')
const { depth: dfwalk } = require('treeverse')
const fs = require('fs')
const { promisify } = require('util')
const lstat = promisify(fs.lstat)
const symlink = promisify(fs.symlink)
const mkdirp = require('mkdirp-infer-owner')
const justMkdirp = require('mkdirp')
const {
lstat,
mkdir,
rm,
symlink,
} = require('fs/promises')
const moveFile = require('@npmcli/move-file')
const rimraf = promisify(require('rimraf'))
const PackageJson = require('@npmcli/package-json')
const packageContents = require('@npmcli/installed-package-contents')
const runScript = require('@npmcli/run-script')
Expand Down Expand Up @@ -175,7 +174,7 @@ module.exports = cls => class Reifier extends cls {
// we do NOT want to set ownership on this folder, especially
// recursively, because it can have other side effects to do that
// in a project directory. We just want to make it if it's missing.
await justMkdirp(resolve(this.path))
await mkdir(resolve(this.path), { recursive: true })

// do not allow the top-level node_modules to be a symlink
await this[_validateNodeModules](resolve(this.path, 'node_modules'))
Expand Down Expand Up @@ -433,10 +432,10 @@ module.exports = cls => class Reifier extends cls {
// handled the most common cause of ENOENT (dir doesn't exist yet),
// then just ignore any ENOENT.
if (er.code === 'ENOENT') {
return didMkdirp ? null : mkdirp(dirname(to)).then(() =>
return didMkdirp ? null : mkdir(dirname(to), { recursive: true }).then(() =>
this[_renamePath](from, to, true))
} else if (er.code === 'EEXIST') {
return rimraf(to).then(() => moveFile(from, to))
return rm(to, { recursive: true, force: true }).then(() => moveFile(from, to))
} else {
throw er
}
Expand Down Expand Up @@ -518,7 +517,7 @@ module.exports = cls => class Reifier extends cls {
await this[_renamePath](d, retired)
}
}
const made = await mkdirp(node.path)
const made = await mkdir(node.path, { recursive: true })
this[_sparseTreeDirs].add(node.path)
this[_sparseTreeRoots].add(made)
}))
Expand All @@ -533,7 +532,7 @@ module.exports = cls => class Reifier extends cls {
const failures = []
const targets = [...roots, ...Object.keys(this[_retiredPaths])]
const unlinks = targets
.map(path => rimraf(path).catch(er => failures.push([path, er])))
.map(path => rm(path, { recursive: true, force: true }).catch(er => failures.push([path, er])))
return promiseAllRejectLate(unlinks).then(() => {
// eslint-disable-next-line promise/always-return
if (failures.length) {
Expand Down Expand Up @@ -630,7 +629,7 @@ module.exports = cls => class Reifier extends cls {
return
}
log.warn('reify', 'Removing non-directory', nm)
await rimraf(nm)
await rm(nm, { recursive: true, force: true })
}

async [_extractOrLink] (node) {
Expand Down Expand Up @@ -664,7 +663,7 @@ module.exports = cls => class Reifier extends cls {
await this[_validateNodeModules](nm)

if (node.isLink) {
await rimraf(node.path)
await rm(node.path, { recursive: true, force: true })
await this[_symlink](node)
} else {
await debug(async () => {
Expand All @@ -690,7 +689,7 @@ module.exports = cls => class Reifier extends cls {
const dir = dirname(node.path)
const target = node.realpath
const rel = relative(dir, target)
await mkdirp(dir)
await mkdir(dir, { recursive: true })
return symlink(rel, node.path, 'junction')
}

Expand Down Expand Up @@ -953,7 +952,7 @@ module.exports = cls => class Reifier extends cls {

// ok! actually unpack stuff into their target locations!
// The sparse tree has already been created, so we walk the diff
// kicking off each unpack job. If any fail, we rimraf the sparse
// kicking off each unpack job. If any fail, we rm the sparse
// tree entirely and try to put everything back where it was.
[_unpackNewModules] () {
process.emit('time', 'reify:unpack')
Expand Down Expand Up @@ -1034,7 +1033,8 @@ module.exports = cls => class Reifier extends cls {
return promiseAllRejectLate(diff.unchanged.map(node => {
// no need to roll back links, since we'll just delete them anyway
if (node.isLink) {
return mkdirp(dirname(node.path)).then(() => this[_reifyNode](node))
return mkdir(dirname(node.path), { recursive: true, force: true })
.then(() => this[_reifyNode](node))
}

// will have been moved/unpacked along with bundler
Expand All @@ -1050,7 +1050,7 @@ module.exports = cls => class Reifier extends cls {
// skip it.
const bd = node.package.bundleDependencies
const dir = bd && bd.length ? node.path + '/node_modules' : node.path
return mkdirp(dir).then(() => this[_moveContents](node, fromPath))
return mkdir(dir, { recursive: true }).then(() => this[_moveContents](node, fromPath))
}))
}))
.then(() => process.emit('timeEnd', 'reify:unretire'))
Expand Down Expand Up @@ -1124,15 +1124,15 @@ module.exports = cls => class Reifier extends cls {
// the tree is pretty much built now, so it's cleanup time.
// remove the retired folders, and any deleted nodes
// If this fails, there isn't much we can do but tell the user about it.
// Thankfully, it's pretty unlikely that it'll fail, since rimraf is a tank.
// Thankfully, it's pretty unlikely that it'll fail, since rm is a tank.
async [_removeTrash] () {
process.emit('time', 'reify:trash')
const promises = []
const failures = []
const rm = path => rimraf(path).catch(er => failures.push([path, er]))
const _rm = path => rm(path, { recursive: true, force: true }).catch(er => failures.push([path, er]))

for (const path of this[_trashList]) {
promises.push(rm(path))
promises.push(_rm(path))
}

await promiseAllRejectLate(promises)
Expand Down
5 changes: 1 addition & 4 deletions workspaces/arborist/lib/realpath.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@
// built-in fs.realpath, because we only care about symbolic links,
// so we can handle many fewer edge cases.

const fs = require('fs')
const promisify = require('util').promisify
const readlink = promisify(fs.readlink)
const lstat = promisify(fs.lstat)
const { lstat, readlink } = require('fs/promises')
const { resolve, basename, dirname } = require('path')

const realpathCached = (path, rpcache, stcache, depth) => {
Expand Down
34 changes: 9 additions & 25 deletions workspaces/arborist/lib/shrinkwrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,30 +35,14 @@ const mismatch = (a, b) => a && b && a !== b

const log = require('proc-log')
const YarnLock = require('./yarn-lock.js')
const { promisify } = require('util')
const rimraf = promisify(require('rimraf'))
const fs = require('fs')
const readFile = promisify(fs.readFile)
const writeFile = promisify(fs.writeFile)
const stat = promisify(fs.stat)
const readdir_ = promisify(fs.readdir)
const readlink = promisify(fs.readlink)

// XXX remove when drop support for node v10
const lstat = promisify(fs.lstat)
/* istanbul ignore next - version specific polyfill */
const readdir = async (path, opt) => {
if (!opt || !opt.withFileTypes) {
return readdir_(path, opt)
}
const ents = await readdir_(path, opt)
if (typeof ents[0] === 'string') {
return Promise.all(ents.map(async ent => {
return Object.assign(await lstat(path + '/' + ent), { name: ent })
}))
}
return ents
}
const {
readFile,
readdir,
readlink,
rm,
stat,
writeFile,
} = require('fs/promises')

const { resolve, basename, relative } = require('path')
const specFromLock = require('./spec-from-lock.js')
Expand Down Expand Up @@ -1153,7 +1137,7 @@ class Shrinkwrap {
// a node_modules folder, but then the lockfile is not important.
// Remove the file, so that in case there WERE deps, but we just
// failed to update the file for some reason, it's not out of sync.
return rimraf(this.filename)
return rm(this.filename, { recursive: true, force: true })
}
throw er
}),
Expand Down
3 changes: 0 additions & 3 deletions workspaces/arborist/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
"json-parse-even-better-errors": "^2.3.1",
"json-stringify-nice": "^1.1.4",
"minimatch": "^5.1.0",
"mkdirp": "^1.0.4",
"mkdirp-infer-owner": "^2.0.0",
"nopt": "^6.0.0",
"npm-install-checks": "^5.0.0",
"npm-package-arg": "^9.0.0",
Expand All @@ -34,7 +32,6 @@
"promise-call-limit": "^1.0.1",
"read-package-json-fast": "^2.0.2",
"readdir-scoped-modules": "^1.1.0",
"rimraf": "^3.0.2",
"semver": "^7.3.7",
"ssri": "^9.0.0",
"treeverse": "^2.0.0",
Expand Down
11 changes: 4 additions & 7 deletions workspaces/arborist/scripts/benchmark.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
process.env.ARBORIST_DEBUG = '0'
const { Suite } = require('benchmark')
const { relative, resolve } = require('path')
const rimraf = require('rimraf')
const { mkdir, rm } = require('fs/promises')
const { execSync } = require('child_process')
const shaCmd = 'git show --no-patch --pretty=%H HEAD'
const dirty = !!String(execSync('git status -s -uno')).trim()
const currentSha = String(execSync(shaCmd)).trim() + (dirty ? '-dirty' : '')
const { green, red } = require('chalk')
const lastBenchmark = resolve(__dirname, 'benchmark/saved/last-benchmark.json')
const mkdirp = require('mkdirp')
const { linkSync, writeFileSync, readdirSync } = require('fs')
const registryServer = require('../test/fixtures/registry-mocks/server.js')

Expand Down Expand Up @@ -152,8 +151,8 @@ const suite = new Suite({
},

async onComplete () {
rimraf.sync(lastBenchmark)
mkdirp.sync(resolve(__dirname, 'benchmark/saved'))
await rm(lastBenchmark, { recursive: true, force: true })
await mkdir(resolve(__dirname, 'benchmark/saved'), { recursive: true })
// always save with sha
const saveThis = resolve(__dirname, `benchmark/saved/${this.sha}.json`)
const data = JSON.stringify(this.reduce((acc, bench) => {
Expand All @@ -171,9 +170,7 @@ const suite = new Suite({
await teardown()
await Promise.all([
registryServer.stop(),
new Promise((res, rej) => {
rimraf(this.cache, er => er ? rej(er) : res())
}),
rm(this.cache, { recursive: true, force: true }),
])
},
})
Expand Down
12 changes: 7 additions & 5 deletions workspaces/arborist/scripts/benchmark/load-actual.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
const Arborist = require('../..')
const { resolve, basename } = require('path')
const { writeFileSync } = require('fs')
const mkdirp = require('mkdirp')
const {
mkdir,
rm,
} = require('fs/promises')
const dir = resolve(__dirname, basename(__filename, '.js'))
const rimraf = require('rimraf')

const suite = async (suite, { registry, cache }) => {
// setup two folders, one with a hidden lockfile, one without
await mkdirp(resolve(dir, 'with-hidden-lockfile'))
await mkdirp(resolve(dir, 'no-hidden-lockfile'))
await mkdir(resolve(dir, 'with-hidden-lockfile'), { recursive: true })
await mkdir(resolve(dir, 'no-hidden-lockfile'), { recursive: true })

const dependencies = {
'flow-parser': '0.114.0',
Expand Down Expand Up @@ -43,7 +45,7 @@ const suite = async (suite, { registry, cache }) => {
dependencies,
}))
promises.push(await arb.reify().then(() =>
rimraf.sync(resolve(arb.path, 'node_modules', '.package-lock.json'))))
rm(resolve(arb.path, 'node_modules', '.package-lock.json'), { recursive: true, force: true })))
}
await Promise.all(promises)

Expand Down
12 changes: 6 additions & 6 deletions workspaces/arborist/scripts/benchmark/reify.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const Arborist = require('../..')
const { resolve, basename } = require('path')
const { writeFileSync } = require('fs')
const mkdirp = require('mkdirp')
const { mkdir } = require('fs/promises')
const { rmSync } = require('fs')
const dir = resolve(__dirname, basename(__filename, '.js'))
const rimraf = require('rimraf')

// these are not arbitrary, the empty/full and no-* bits matter
const folders = [
Expand All @@ -19,7 +19,7 @@ const folders = [

const suite = async (suite, { registry, cache }) => {
// setup two folders, one with a hidden lockfile, one without
await Promise.all(folders.map(f => mkdirp(f)))
await Promise.all(folders.map(f => mkdir(f, { recursive: true })))

const dependencies = {
'flow-parser': '0.114.0',
Expand Down Expand Up @@ -86,13 +86,13 @@ const suite = async (suite, { registry, cache }) => {
defer: true,
setup () {
if (/no-lockfile/.test(path)) {
rimraf.sync(resolve(path, 'package-lock.json'))
rmSync(resolve(path, 'package-lock.json'), { recursive: true, force: true })
}
if (/empty/.test(path)) {
rimraf.sync(resolve(path, 'node_modules'))
rmSync(resolve(path, 'node_modules'), { recursive: true, force: true })
}
if (/no-cache/.test(path)) {
rimraf.sync(resolve(path, 'cache'))
rmSync(resolve(path, 'cache'), { recursive: true, force: true })
}
},
async fn (d) {
Expand Down
Loading

0 comments on commit 849ef58

Please sign in to comment.