Skip to content

Commit

Permalink
feat: overwrite option
Browse files Browse the repository at this point in the history
  • Loading branch information
zkochan committed Nov 20, 2022
1 parent 27b37f2 commit e0b4988
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 5 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2016-2021 Zoltan Kochan <z@kochan.io>
Copyright (c) 2016-2022 Zoltan Kochan <z@kochan.io>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,14 @@ symlinkDir('src', 'node_modules/src')

## API

### `symlinkDir(src, dest): Promise<{ reused: boolean, warn?: string }>`
### `symlinkDir(src, dest, opts?): Promise<{ reused: boolean, warn?: string }>`

Creates a symlink in `dest` that points to `src`.

Options:

* `overwrite` - *boolean* - is `true` by default. When `false`, existing files at dest are not overwritten.

Result:

* `reused` - *boolean* - is `true` if the symlink already existed pointing to the `src`.
Expand Down
9 changes: 6 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,22 @@ function resolveSrcOnNonWin (src: string, dest: string) {
return path.relative(path.dirname(dest), src)
}

function symlinkDir (src: string, dest: string): Promise<{ reused: Boolean, warn?: string }> {
function symlinkDir (src: string, dest: string, opts?: { overwrite?: boolean }): Promise<{ reused: Boolean, warn?: string }> {
dest = betterPathResolve(dest)
src = betterPathResolve(src)

if (src === dest) throw new Error(`Symlink path is the same as the target path (${src})`)

src = resolveSrc(src, dest)

return forceSymlink(src, dest)
return forceSymlink(src, dest, opts)
}

/**
* Creates a symlink. Re-link if a symlink already exists at the supplied
* srcPath. API compatible with [`fs#symlink`](https://nodejs.org/api/fs.html#fs_fs_symlink_srcpath_dstpath_type_callback).
*/
async function forceSymlink (src: string, dest: string): Promise<{ reused: Boolean, warn?: string }> {
async function forceSymlink (src: string, dest: string, opts?: { overwrite?: boolean }): Promise<{ reused: Boolean, warn?: string }> {
try {
await fs.symlink(src, dest, symlinkType)
return { reused: false }
Expand All @@ -53,6 +53,9 @@ async function forceSymlink (src: string, dest: string): Promise<{ reused: Boole
return { reused: false }
case 'EEXIST':
case 'EISDIR':
if (opts?.overwrite === false) {
throw err
}
// If the target file already exists then we proceed.
// Additional checks are done below.
break
Expand Down
35 changes: 35 additions & 0 deletions test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,25 @@ test('rename target folder if it exists', async (t) => {
t.end()
})

test('do not rename target folder if overwrite is set to false', async (t) => {
const temp = tempy.directory()
t.comment(`testing in ${temp}`)
process.chdir(temp)

await fs.mkdir('src')
await fs.mkdir('dest')

let err!: Error
try {
await symlink('src', 'dest', { overwrite: false })
} catch (_err) {
err = _err
}

t.equals(err['code'], 'EEXIST', 'dest folder not ignored')
t.end()
})

test('rename target file if it exists', async (t) => {
const temp = tempy.directory()
t.comment(`testing in ${temp}`)
Expand Down Expand Up @@ -86,3 +105,19 @@ test('concurrently creating the same symlink twice', async (t) => {

t.end()
})

test('reusing the existing symlink if it already points to the needed location', async (t) => {
const temp = tempy.directory()
t.comment(`testing in ${temp}`)
process.chdir(temp)

await writeJsonFile('src/file.json', { ok: true })

await symlink('src', 'dest/subdir')
const { reused } = await symlink('src', 'dest/subdir')

t.equal(reused, true)
t.deepEqual(await import(path.resolve('dest/subdir/file.json')), { ok: true })

t.end()
})

0 comments on commit e0b4988

Please sign in to comment.