From f1bcafc5840f73716a668ef99b04fcbed494817d Mon Sep 17 00:00:00 2001 From: Yun Lai <lyonlai1984@gmail.com> Date: Tue, 26 Jul 2022 18:19:20 +1000 Subject: [PATCH] feat(fs): add localPathIsSymbolicLink and readLocalSymlink (#16673) * fix: add localPathIsSymbolicLink and readLocalSymlink to fs module * Update lib/util/fs/index.ts Co-authored-by: Michael Kriese <michael.kriese@visualon.de> * Update lib/util/fs/index.ts * Apply suggestions from code review Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com> Co-authored-by: Michael Kriese <michael.kriese@visualon.de> Co-authored-by: Rhys Arkins <rhys@arkins.net> Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com> --- lib/util/fs/index.spec.ts | 57 +++++++++++++++++++++++++++++++++++++++ lib/util/fs/index.ts | 25 +++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/lib/util/fs/index.spec.ts b/lib/util/fs/index.spec.ts index 0f221e33e1..6a257f0127 100644 --- a/lib/util/fs/index.spec.ts +++ b/lib/util/fs/index.spec.ts @@ -18,11 +18,13 @@ import { listCacheDir, localPathExists, localPathIsFile, + localPathIsSymbolicLink, outputCacheFile, privateCacheDir, readCacheFile, readLocalDirectory, readLocalFile, + readLocalSymlink, readSystemFile, renameLocalFile, rmCache, @@ -204,6 +206,32 @@ describe('util/fs/index', () => { }); }); + describe('readLocalSymlink', () => { + it('reads symlink', async () => { + await writeLocalFile('test/test.txt', ''); + await fs.symlink( + join(localDir, 'test/test.txt'), + join(localDir, 'test/test') + ); + + const result = await readLocalSymlink('test/test'); + + expect(result).not.toBeNull(); + }); + + it('return null when link not exists', async () => { + await writeLocalFile('test/test.txt', ''); + await fs.symlink( + join(localDir, 'test/test.txt'), + join(localDir, 'test/test') + ); + + const notExistsResult = await readLocalSymlink('test/not-exists'); + + expect(notExistsResult).toBeNull(); + }); + }); + describe('findLocalSiblingOrParent', () => { it('returns path for file', async () => { await writeLocalFile('crates/one/Cargo.toml', 'foo'); @@ -301,6 +329,35 @@ describe('util/fs/index', () => { }); }); + describe('localPathIsSymbolicLink', () => { + it('returns false for file', async () => { + const path = `${localDir}/file.txt`; + await fs.outputFile(path, 'foobar'); + expect(await localPathIsSymbolicLink(path)).toBeFalse(); + }); + + it('returns false for directory', async () => { + const path = `${localDir}/foobar`; + await fs.mkdir(path); + expect(await localPathIsSymbolicLink(path)).toBeFalse(); + }); + + it('returns false for non-existing path', async () => { + const path = `${localDir}/file.txt`; + expect(await localPathIsSymbolicLink(path)).toBeFalse(); + }); + + it('returns true for symlink', async () => { + const source = `${localDir}/test/test.txt`; + const target = `${localDir}/test/test`; + await fs.outputFile(source, 'foobar'); + await fs.symlink(source, target); + + const result = await localPathIsSymbolicLink('test/test'); + expect(result).toBeTrue(); + }); + }); + describe('findUpLocal', () => { beforeEach(() => { GlobalConfig.set({ localDir: '/abs/path/to/local/dir' }); diff --git a/lib/util/fs/index.ts b/lib/util/fs/index.ts index c3cb9a7419..6f65fecc80 100644 --- a/lib/util/fs/index.ts +++ b/lib/util/fs/index.ts @@ -43,6 +43,19 @@ export async function readLocalFile( } } +export async function readLocalSymlink( + fileName: string +): Promise<string | null> { + const localFileName = ensureLocalPath(fileName); + try { + const linkContent = await fs.readlink(localFileName); + return linkContent; + } catch (err) { + logger.trace({ err }, 'Error reading local symlink'); + return null; + } +} + export async function writeLocalFile( fileName: string, fileContent: string | Buffer @@ -160,6 +173,18 @@ export async function localPathIsFile(pathName: string): Promise<boolean> { } } +export async function localPathIsSymbolicLink( + pathName: string +): Promise<boolean> { + const path = ensureLocalPath(pathName); + try { + const s = await fs.lstat(path); + return s.isSymbolicLink(); + } catch (_) { + return false; + } +} + /** * Find a file or directory by walking up parent directories within localDir */ -- GitLab