-
Notifications
You must be signed in to change notification settings - Fork 333
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix Yarn detection when using workspaces, fix
.yarnrc.yml
loading (#…
…1148) Co-authored-by: Raine Revere <[email protected]>
- Loading branch information
1 parent
c81980c
commit e445722
Showing
7 changed files
with
284 additions
and
37 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import fs from 'fs' | ||
import { Options } from '../types/Options' | ||
import findLockfile from './findLockfile' | ||
|
||
const defaultPackageManager = 'npm' | ||
|
||
/** | ||
* If the packageManager option was not provided, look at the lockfiles to | ||
* determine which package manager is being used. | ||
* | ||
* @param readdirSync This is only a parameter so that it can be used in tests. | ||
*/ | ||
export default function determinePackageManager( | ||
options: Options, | ||
readdirSync: (_path: string) => string[] = fs.readdirSync, | ||
): string { | ||
if (options.packageManager) return options.packageManager | ||
if (options.global) return defaultPackageManager | ||
|
||
const lockfileName = findLockfile(options, readdirSync)?.filename | ||
|
||
if (lockfileName === 'package-lock.json') return 'npm' | ||
if (lockfileName === 'yarn.lock') return 'yarn' | ||
|
||
return defaultPackageManager | ||
} |
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,44 @@ | ||
import fs from 'fs' | ||
import path from 'path' | ||
import { Options } from '../types/Options' | ||
|
||
/** | ||
* Goes up the filesystem tree until it finds a package-lock.json or yarn.lock. | ||
* | ||
* @param readdirSync This is only a parameter so that it can be used in tests. | ||
* @returns The path of the directory that contains the lockfile and the | ||
* filename of the lockfile. | ||
*/ | ||
export default function findLockfile( | ||
options: Pick<Options, 'cwd' | 'packageFile'>, | ||
readdirSync: (_path: string) => string[] = fs.readdirSync, | ||
): { directoryPath: string; filename: string } | null { | ||
try { | ||
// 1. explicit cwd | ||
// 2. same directory as package file | ||
// 3. current directory | ||
let currentPath = options.cwd ? options.cwd : options.packageFile ? path.dirname(options.packageFile) : '.' | ||
|
||
// eslint-disable-next-line fp/no-loops | ||
while (true) { | ||
const files = readdirSync(currentPath) | ||
|
||
if (files.includes('package-lock.json')) { | ||
return { directoryPath: currentPath, filename: 'package-lock.json' } | ||
} | ||
|
||
if (files.includes('yarn.lock')) { | ||
return { directoryPath: currentPath, filename: 'yarn.lock' } | ||
} | ||
|
||
const pathParent = path.resolve(currentPath, '..') | ||
if (pathParent === currentPath) break | ||
|
||
currentPath = pathParent | ||
} | ||
} catch (e) { | ||
// if readdirSync fails, return null | ||
} | ||
|
||
return null | ||
} |
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,96 @@ | ||
import chai from 'chai' | ||
import determinePackageManager from '../src/lib/determinePackageManager' | ||
|
||
chai.should() | ||
|
||
const isWindows = process.platform === 'win32' | ||
|
||
it('returns options.packageManager if set', () => { | ||
determinePackageManager({ packageManager: 'fake' }).should.equal('fake') | ||
}) | ||
|
||
it('returns yarn if yarn.lock exists in cwd', () => { | ||
/** Mock for filesystem calls. */ | ||
function readdirSyncMock(path: string): string[] { | ||
switch (path) { | ||
case '/home/test-repo': | ||
case 'C:\\home\\test-repo': | ||
return ['yarn.lock'] | ||
} | ||
|
||
throw new Error(`Mock cannot handle path: ${path}.`) | ||
} | ||
|
||
determinePackageManager( | ||
{ | ||
cwd: isWindows ? 'C:\\home\\test-repo' : '/home/test-repo', | ||
}, | ||
readdirSyncMock, | ||
).should.equal('yarn') | ||
}) | ||
|
||
it('returns yarn if yarn.lock exists in an ancestor directory', () => { | ||
/** Mock for filesystem calls. */ | ||
function readdirSyncMock(path: string): string[] { | ||
switch (path) { | ||
case '/home/test-repo/packages/package-a': | ||
case 'C:\\home\\test-repo\\packages\\package-a': | ||
return ['index.ts'] | ||
case '/home/test-repo/packages': | ||
case 'C:\\home\\test-repo\\packages': | ||
return [] | ||
case '/home/test-repo': | ||
case 'C:\\home\\test-repo': | ||
return ['yarn.lock'] | ||
} | ||
|
||
throw new Error(`Mock cannot handle path: ${path}.`) | ||
} | ||
|
||
determinePackageManager( | ||
{ | ||
cwd: isWindows ? 'C:\\home\\test-repo\\packages\\package-a' : '/home/test-repo/packages/package-a', | ||
}, | ||
readdirSyncMock, | ||
).should.equal('yarn') | ||
}) | ||
|
||
it('returns npm if package-lock.json found before yarn.lock', () => { | ||
/** Mock for filesystem calls. */ | ||
function readdirSyncMock(path: string): string[] { | ||
switch (path) { | ||
case '/home/test-repo/packages/package-a': | ||
case 'C:\\home\\test-repo\\packages\\package-a': | ||
return ['index.ts'] | ||
case '/home/test-repo/packages': | ||
case 'C:\\home\\test-repo\\packages': | ||
return ['package-lock.json'] | ||
case '/home/test-repo': | ||
case 'C:\\home\\test-repo': | ||
return ['yarn.lock'] | ||
} | ||
|
||
throw new Error(`Mock cannot handle path: ${path}.`) | ||
} | ||
|
||
determinePackageManager( | ||
{ | ||
cwd: isWindows ? 'C:\\home\\test-repo\\packages\\package-a' : '/home/test-repo/packages/package-a', | ||
}, | ||
readdirSyncMock, | ||
).should.equal('npm') | ||
}) | ||
|
||
it('does not loop infinitely if no lockfile found', () => { | ||
/** Mock for filesystem calls. */ | ||
function readdirSyncMock(): string[] { | ||
return [] | ||
} | ||
|
||
determinePackageManager( | ||
{ | ||
cwd: isWindows ? 'C:\\home\\test-repo\\packages\\package-a' : '/home/test-repo/packages/package-a', | ||
}, | ||
readdirSyncMock, | ||
).should.equal('npm') | ||
}) |
Oops, something went wrong.