-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This also removes `readdir-scoped-modules` and `@npmcli/fs` since those are now a part of `@npmcli/fs`
- Loading branch information
1 parent
50d2ec2
commit b58d396
Showing
30 changed files
with
169 additions
and
995 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
const { dirname, join, resolve, relative, isAbsolute } = require('path') | ||
const fs = require('fs/promises') | ||
|
||
const pathExists = async path => { | ||
try { | ||
await fs.access(path) | ||
return true | ||
} catch (er) { | ||
return er.code !== 'ENOENT' | ||
} | ||
} | ||
|
||
const moveFile = async (source, destination, options = {}, root = true, symlinks = []) => { | ||
if (!source || !destination) { | ||
throw new TypeError('`source` and `destination` file required') | ||
} | ||
|
||
options = { | ||
overwrite: true, | ||
...options, | ||
} | ||
|
||
if (!options.overwrite && await pathExists(destination)) { | ||
throw new Error(`The destination file exists: ${destination}`) | ||
} | ||
|
||
await fs.mkdir(dirname(destination), { recursive: true }) | ||
|
||
try { | ||
await fs.rename(source, destination) | ||
} catch (error) { | ||
if (error.code === 'EXDEV' || error.code === 'EPERM') { | ||
const sourceStat = await fs.lstat(source) | ||
if (sourceStat.isDirectory()) { | ||
const files = await fs.readdir(source) | ||
await Promise.all(files.map((file) => | ||
moveFile(join(source, file), join(destination, file), options, false, symlinks) | ||
)) | ||
} else if (sourceStat.isSymbolicLink()) { | ||
symlinks.push({ source, destination }) | ||
} else { | ||
await fs.copyFile(source, destination) | ||
} | ||
} else { | ||
throw error | ||
} | ||
} | ||
|
||
if (root) { | ||
await Promise.all(symlinks.map(async ({ source: symSource, destination: symDestination }) => { | ||
let target = await fs.readlink(symSource) | ||
// junction symlinks in windows will be absolute paths, so we need to | ||
// make sure they point to the symlink destination | ||
if (isAbsolute(target)) { | ||
target = resolve(symDestination, relative(symSource, target)) | ||
} | ||
// try to determine what the actual file is so we can create the correct | ||
// type of symlink in windows | ||
let targetStat = 'file' | ||
try { | ||
targetStat = await fs.stat(resolve(dirname(symSource), target)) | ||
if (targetStat.isDirectory()) { | ||
targetStat = 'junction' | ||
} | ||
} catch { | ||
// targetStat remains 'file' | ||
} | ||
await fs.symlink( | ||
target, | ||
symDestination, | ||
targetStat | ||
) | ||
})) | ||
await fs.rm(source, { recursive: true, force: true }) | ||
} | ||
} | ||
|
||
module.exports = moveFile |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
const { readdir } = require('fs/promises') | ||
const { join } = require('path') | ||
|
||
const readdirScoped = async (dir) => { | ||
const results = [] | ||
|
||
for (const item of await readdir(dir)) { | ||
if (item.startsWith('@')) { | ||
for (const scopedItem of await readdir(join(dir, item))) { | ||
results.push(join(item, scopedItem)) | ||
} | ||
} else { | ||
results.push(item) | ||
} | ||
} | ||
|
||
return results | ||
} | ||
|
||
module.exports = readdirScoped |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.