Skip to content
This repository was archived by the owner on May 22, 2024. It is now read-only.

Commit db2f959

Browse files
authored
fix: create symlink parent directory before creating symlink itself (#1709)
* fix: don't swallow beginning of path * chore: add repro * fix: create link parent directory before creating link
1 parent 9e82c5a commit db2f959

File tree

5 files changed

+52
-7
lines changed

5 files changed

+52
-7
lines changed

src/runtimes/node/utils/zip.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Buffer } from 'buffer'
22
import { Stats } from 'fs'
33
import { mkdir, readlink as readLink, rm, symlink, writeFile } from 'fs/promises'
44
import os from 'os'
5-
import { basename, extname, join } from 'path'
5+
import { basename, extname, join, dirname } from 'path'
66

77
import { getPath as getV2APIPath } from '@netlify/serverless-functions-api'
88
import { copyFile } from 'cp-file'
@@ -154,9 +154,16 @@ const createDirectory = async function ({
154154
{ concurrency: COPY_FILE_CONCURRENCY },
155155
)
156156

157-
await pMap([...symlinks.entries()], ([target, path]) => symlink(target, path), {
158-
concurrency: COPY_FILE_CONCURRENCY,
159-
})
157+
await pMap(
158+
[...symlinks.entries()],
159+
async ([target, path]) => {
160+
await mkdir(dirname(path), { recursive: true })
161+
await symlink(target, path)
162+
},
163+
{
164+
concurrency: COPY_FILE_CONCURRENCY,
165+
},
166+
)
160167

161168
return { path: functionFolder, entryFilename }
162169
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default () => console.log('hello world')

tests/fixtures-esm/symlinked-bin/subproject/node_modules/.bin/cli.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/fixtures-esm/symlinked-bin/subproject/node_modules/tool/cli.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/symlinked_included_files.test.ts

+38-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const readDirWithType = async (dir: string, readFiles?: Record<string, boolean>,
1717

1818
for (const dirent of dirents) {
1919
if (dirent.isDirectory()) {
20-
await readDirWithType(join(dir, dirent.name), files, dirent.name)
20+
await readDirWithType(join(dir, dirent.name), files, join(parent, dirent.name))
2121
} else {
2222
files[join(parent, dirent.name)] = dirent.isSymbolicLink()
2323
}
@@ -34,7 +34,7 @@ test.skipIf(platform() === 'win32')('Symlinked directories from `includedFiles`
3434
// assert on the source files
3535
expect(await readDirWithType(basePath)).toEqual({
3636
'function.mjs': false,
37-
[join('crazy-dep/package.json')]: false,
37+
[join('node_modules/.pnpm/crazy-dep/package.json')]: false,
3838
[join('node_modules/crazy-dep')]: true,
3939
})
4040

@@ -63,7 +63,42 @@ test.skipIf(platform() === 'win32')('Symlinked directories from `includedFiles`
6363
'___netlify-bootstrap.mjs': false,
6464
'___netlify-entry-point.mjs': false,
6565
'function.mjs': false,
66-
[join('crazy-dep/package.json')]: false,
66+
[join('node_modules/.pnpm/crazy-dep/package.json')]: false,
6767
[join('node_modules/crazy-dep')]: true,
6868
})
6969
})
70+
71+
test.skipIf(platform() === 'win32')('symlinks in subdir of `includedFiles` are copied over successfully', async () => {
72+
const { path: tmpDir } = await getTmpDir({ prefix: 'zip-it-test' })
73+
const basePath = join(FIXTURES_ESM_DIR, 'symlinked-bin')
74+
const mainFile = join(basePath, 'function.ts')
75+
76+
// assert on the source files
77+
expect(await readDirWithType(basePath)).toEqual({
78+
'function.ts': false,
79+
[join('subproject/node_modules/.bin/cli.js')]: true,
80+
[join('subproject/node_modules/tool/cli.js')]: false,
81+
})
82+
83+
await zipFunction(mainFile, tmpDir, {
84+
archiveFormat: ARCHIVE_FORMAT.NONE,
85+
basePath,
86+
config: {
87+
'*': {
88+
includedFiles: ['subproject/**'],
89+
},
90+
},
91+
repositoryRoot: basePath,
92+
systemLog: console.log,
93+
debug: true,
94+
internalSrcFolder: undefined,
95+
})
96+
97+
expect(await readDirWithType(join(tmpDir, 'function'))).toEqual({
98+
'___netlify-bootstrap.mjs': false,
99+
'___netlify-entry-point.mjs': false,
100+
'function.cjs': false,
101+
'subproject/node_modules/.bin/cli.js': true,
102+
'subproject/node_modules/tool/cli.js': false,
103+
})
104+
})

0 commit comments

Comments
 (0)