Skip to content

Commit

Permalink
fix: ignore file duplicates on case insensitive filesystems
Browse files Browse the repository at this point in the history
ref #1685
  • Loading branch information
zkochan committed Mar 17, 2019
1 parent ab57ad0 commit ba02468
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 19 deletions.
1 change: 1 addition & 0 deletions packages/default-fetcher/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import createTarballFetcher, {
export default function (
opts: {
alwaysAuth?: boolean,
fsIsCaseSensitive?: boolean,
registry: string,
rawNpmConfig: object,
strictSsl?: boolean,
Expand Down
1 change: 1 addition & 0 deletions packages/pnpm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"cross-spawn": "6.0.5",
"delay": "4.1.0",
"diable": "4.0.2",
"dir-is-case-sensitive": "0.0.0",
"execa": "1.0.0",
"find-packages": "4.0.1",
"get-port": "4.2.0",
Expand Down
6 changes: 5 additions & 1 deletion packages/pnpm/src/createStore.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import createFetcher from '@pnpm/default-fetcher'
import createResolver from '@pnpm/default-resolver'
import createStore from '@pnpm/package-store'
import dirIsCaseSensitive from 'dir-is-case-sensitive'
import LRU = require('lru-cache')
import mkdirp = require('mkdirp-promise')
import path = require('path')

export default async (
Expand Down Expand Up @@ -43,7 +45,9 @@ export default async (
maxAge: 120 * 1000, // 2 minutes
}) as any, // tslint:disable-line:no-any
}))
const fetchers = createFetcher(sopts)
await mkdirp(sopts.store)
const fsIsCaseSensitive = await dirIsCaseSensitive(sopts.store)
const fetchers = createFetcher({ ...sopts, fsIsCaseSensitive })
return {
ctrl: await createStore(resolve, fetchers as {}, {
locks: sopts.locks,
Expand Down
9 changes: 9 additions & 0 deletions packages/pnpm/test/install/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,12 @@ test('install save new dep with the specified spec', async (t: tape.Test) => {

t.deepEqual(pkg.dependencies, { 'is-positive': '~3.1.0' })
})

// Covers https://github.com/pnpm/pnpm/issues/1685
test("don't fail on Windows when package has 2 files with same name", async (t) => {
const project = prepare(t)

await execPnpm('install', 'with-same-file-in-different-cases')

await project.has('with-same-file-in-different-cases')
})
9 changes: 0 additions & 9 deletions packages/supi/test/install/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -914,12 +914,3 @@ test('rewrites node_modules created by npm', async (t) => {

await install(await testDefaults())
})

// Covers https://github.com/pnpm/pnpm/issues/1685
test("don't fail on Windows when package has 2 files with same name", async (t) => {
const project = prepare(t)

await addDependenciesToPackage(['with-same-file-in-different-cases'], await testDefaults())

await project.has('with-same-file-in-different-cases')
})
2 changes: 1 addition & 1 deletion packages/tarball-fetcher/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"retry": "0.12.0",
"rimraf": "2.6.3",
"ssri": "6.0.1",
"unpack-stream": "4.0.2"
"unpack-stream": "4.0.1"
},
"devDependencies": {
"@pnpm/logger": "2.1.0",
Expand Down
26 changes: 25 additions & 1 deletion packages/tarball-fetcher/src/createDownloader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface NpmRegistryClient {
export default (
gotOpts: {
alwaysAuth: boolean,
fsIsCaseSensitive: boolean,
registry: string,
// proxy
proxy?: string,
Expand Down Expand Up @@ -160,11 +161,12 @@ export default (
.on('error', reject)

const tempLocation = pathTemp(opts.unpackTo)
const ignore = gotOpts.fsIsCaseSensitive ? opts.ignore : createIgnorer(opts.ignore)
Promise.all([
opts.integrity && safeCheckStream(res.body, opts.integrity) || true,
unpackStream.local(res.body, tempLocation, {
generateIntegrity: opts.generatePackageIntegrity,
ignore: opts.ignore,
ignore,
}),
waitTillClosed({ stream, size, getDownloaded: () => downloaded, url }),
])
Expand Down Expand Up @@ -197,6 +199,28 @@ export default (
}
}

function createIgnorer (ignore?: (filename: string) => Boolean) {
const lowercaseFiles = new Set<string>()
if (ignore) {
return (filename: string) => {
const lowercaseFilename = filename.toLowerCase()
if (lowercaseFiles.has(lowercaseFilename)) {
return true
}
lowercaseFiles.add(lowercaseFilename)
return ignore(filename)
}
}
return (filename: string) => {
const lowercaseFilename = filename.toLowerCase()
if (lowercaseFiles.has(lowercaseFilename)) {
return true
}
lowercaseFiles.add(lowercaseFilename)
return false
}
}

async function safeCheckStream (stream: any, integrity: string): Promise<true | Error> { // tslint:disable-line:no-any
try {
await ssri.checkStream(stream, integrity)
Expand Down
2 changes: 2 additions & 0 deletions packages/tarball-fetcher/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@ export default function (
userAgent?: string,
ignoreFile?: IgnoreFunction,
offline?: boolean,
fsIsCaseSensitive?: boolean,
},
): { tarball: FetchFunction } {
const download = createDownloader({
alwaysAuth: opts.alwaysAuth || false,
ca: opts.ca,
cert: opts.cert,
fsIsCaseSensitive: opts.fsIsCaseSensitive || true, // TODO: change the default value to false
key: opts.key,
localAddress: opts.localAddress,
proxy: opts.httpsProxy || opts.proxy,
Expand Down
25 changes: 18 additions & 7 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit ba02468

Please sign in to comment.