Skip to content

Commit

Permalink
feat: deploy command
Browse files Browse the repository at this point in the history
close #4378
  • Loading branch information
zkochan committed Jun 26, 2022
1 parent 148a104 commit 316b51d
Show file tree
Hide file tree
Showing 36 changed files with 427 additions and 60 deletions.
1 change: 1 addition & 0 deletions .meta-updater/src/index.ts
Expand Up @@ -137,6 +137,7 @@ async function updateManifest (workspaceDir: string, manifest: ProjectManifest,
case '@pnpm/plugin-commands-rebuild':
case '@pnpm/plugin-commands-script-runners':
case '@pnpm/plugin-commands-store':
case '@pnpm/plugin-commands-deploy':
case CLI_PKG_NAME:
case '@pnpm/core': {
// @pnpm/core tests currently works only with port 4873 due to the usage of
Expand Down
27 changes: 27 additions & 0 deletions packages/core/src/install/index.ts
Expand Up @@ -812,6 +812,33 @@ const _installInContext: InstallFunction = async (projects, ctx, opts) => {
patchedDependencies: opts.patchedDependencies,
}
)
if (!opts.include.optionalDependencies || !opts.include.devDependencies || !opts.include.dependencies) {
for (const projectId of Object.keys(linkedDependenciesByProjectId ?? {})) {
linkedDependenciesByProjectId[projectId] = linkedDependenciesByProjectId[projectId].filter((linkedDep) =>
!(
linkedDep.dev && !opts.include.devDependencies ||
linkedDep.optional && !opts.include.optionalDependencies ||
!linkedDep.dev && !linkedDep.optional && !opts.include.dependencies
)
)
}
for (const { id, manifest } of projects) {
dependenciesByProjectId[id] = fromPairs(
Object.entries(dependenciesByProjectId[id])
.filter(([, depPath]) => {
const dep = dependenciesGraph[depPath]
if (!dep) return false
const isDev = Boolean(manifest.devDependencies?.[dep.name])
const isOptional = Boolean(manifest.optionalDependencies?.[dep.name])
return !(
isDev && !opts.include.devDependencies ||
isOptional && !opts.include.optionalDependencies ||
!isDev && !isOptional && !opts.include.dependencies
)
})
)
}
}

stageLogger.debug({
prefix: ctx.lockfileDir,
Expand Down
9 changes: 2 additions & 7 deletions packages/core/src/install/link.ts
Expand Up @@ -165,17 +165,12 @@ export default async function linkPackages (
.map(([rootAlias, depPath]) => ({ rootAlias, depGraphNode: depGraph[depPath] }))
.filter(({ depGraphNode }) => depGraphNode)
.map(async ({ rootAlias, depGraphNode }) => {
const isDev = Boolean(manifest.devDependencies?.[depGraphNode.name])
const isOptional = Boolean(manifest.optionalDependencies?.[depGraphNode.name])
if (
isDev && !opts.include.devDependencies ||
isOptional && !opts.include.optionalDependencies ||
!isDev && !isOptional && !opts.include.dependencies
) return
if (
(await symlinkDependency(depGraphNode.dir, modulesDir, rootAlias)).reused
) return

const isDev = Boolean(manifest.devDependencies?.[depGraphNode.name])
const isOptional = Boolean(manifest.optionalDependencies?.[depGraphNode.name])
rootLogger.debug({
added: {
dependencyType: isDev && 'dev' || isOptional && 'optional' || 'prod',
Expand Down
16 changes: 4 additions & 12 deletions packages/create-cafs-store/package.json
Expand Up @@ -16,17 +16,11 @@
},
"dependencies": {
"@pnpm/cafs": "workspace:4.0.7",
"@pnpm/core-loggers": "workspace:7.0.5",
"@pnpm/fetcher-base": "workspace:13.0.1",
"@pnpm/fs.indexed-pkg-importer": "workspace:0.0.0",
"@pnpm/store-controller-types": "workspace:14.0.1",
"@zkochan/rimraf": "^2.1.2",
"make-empty-dir": "^2.0.0",
"mem": "^8.0.0",
"p-limit": "^3.1.0",
"path-exists": "^4.0.0",
"path-temp": "^2.0.0",
"rename-overwrite": "^4.0.2",
"sanitize-filename": "^1.6.3"
"path-temp": "^2.0.0"
},
"devDependencies": {
"@pnpm/create-cafs-store": "workspace:2.0.1",
Expand Down Expand Up @@ -55,10 +49,8 @@
"scripts": {
"start": "tsc --watch",
"fix": "tslint -c tslint.json src/**/*.ts test/**/*.ts --fix",
"lint": "eslint src/**/*.ts test/**/*.ts",
"pretest": "rimraf .tmp",
"_test": "pnpm pretest && jest",
"test": "pnpm run compile && pnpm run _test",
"lint": "eslint src/**/*.ts",
"test": "pnpm run compile",
"prepublishOnly": "pnpm run compile",
"compile": "tsc --build && pnpm run lint --fix"
},
Expand Down
4 changes: 2 additions & 2 deletions packages/create-cafs-store/src/index.ts
Expand Up @@ -4,21 +4,21 @@ import createCafs, {
getFilePathByModeInCafs,
} from '@pnpm/cafs'
import { PackageFilesResponse } from '@pnpm/fetcher-base'
import { createIndexedPkgImporter } from '@pnpm/fs.indexed-pkg-importer'
import {
ImportPackageFunction,
PackageFileInfo,
} from '@pnpm/store-controller-types'
import memoize from 'mem'
import pathTemp from 'path-temp'
import createImportPackage from './createImportPackage'

function createPackageImporter (
opts: {
packageImportMethod?: 'auto' | 'hardlink' | 'copy' | 'clone' | 'clone-or-copy'
cafsDir: string
}
): ImportPackageFunction {
const cachedImporterCreator = memoize(createImportPackage)
const cachedImporterCreator = memoize(createIndexedPkgImporter)
const packageImportMethod = opts.packageImportMethod
const gfm = getFlatMap.bind(null, opts.cafsDir)
return async (to, opts) => {
Expand Down
4 changes: 2 additions & 2 deletions packages/create-cafs-store/tsconfig.json
Expand Up @@ -16,10 +16,10 @@
"path": "../cafs"
},
{
"path": "../core-loggers"
"path": "../fetcher-base"
},
{
"path": "../fetcher-base"
"path": "../fs.indexed-pkg-importer"
},
{
"path": "../store-controller-types"
Expand Down
13 changes: 13 additions & 0 deletions packages/fs.indexed-pkg-importer/README.md
@@ -0,0 +1,13 @@
# @pnpm/create-cafs-store

> Replicates indexed directories using hard links, copies, or cloning
## Installation

```
pnpm add @pnpm/create-cafs-store
```

## License

[MIT](LICENSE)
3 changes: 3 additions & 0 deletions packages/fs.indexed-pkg-importer/jest.config.js
@@ -0,0 +1,3 @@
const config = require('../../jest.config.js');

module.exports = Object.assign({}, config, {});
65 changes: 65 additions & 0 deletions packages/fs.indexed-pkg-importer/package.json
@@ -0,0 +1,65 @@
{
"name": "@pnpm/fs.indexed-pkg-importer",
"description": "Replicates indexed directories using hard links, copies, or cloning",
"version": "0.0.0",
"bugs": {
"url": "https://github.com/pnpm/pnpm/issues"
},
"main": "lib/index.js",
"types": "lib/index.d.ts",
"files": [
"lib",
"!*.map"
],
"peerDependencies": {
"@pnpm/logger": "^4.0.0"
},
"dependencies": {
"@pnpm/core-loggers": "workspace:7.0.5",
"@zkochan/rimraf": "^2.1.2",
"make-empty-dir": "^2.0.0",
"p-limit": "^3.1.0",
"path-exists": "^4.0.0",
"path-temp": "^2.0.0",
"rename-overwrite": "^4.0.2",
"sanitize-filename": "^1.6.3"
},
"devDependencies": {
"@pnpm/fs.indexed-pkg-importer": "workspace:0.0.0",
"@pnpm/logger": "^4.0.0",
"@pnpm/prepare": "workspace:*"
},
"directories": {
"test": "test"
},
"homepage": "https://github.com/pnpm/pnpm/blob/main/packages/fs.indexed-pkg-importer#readme",
"keywords": [
"pnpm7",
"store",
"storage",
"global store",
"maching store",
"central storage",
"cache",
"packages"
],
"license": "MIT",
"engines": {
"node": ">=14.6"
},
"repository": "https://github.com/pnpm/pnpm/blob/main/packages/fs.indexed-pkg-importer",
"scripts": {
"start": "tsc --watch",
"fix": "tslint -c tslint.json src/**/*.ts test/**/*.ts --fix",
"lint": "eslint src/**/*.ts test/**/*.ts",
"pretest": "rimraf .tmp",
"_test": "pnpm pretest && jest",
"test": "pnpm run compile && pnpm run _test",
"prepublishOnly": "pnpm run compile",
"compile": "tsc --build && pnpm run lint --fix"
},
"funding": "https://opencollective.com/pnpm",
"exports": {
".": "./lib/index.js"
}
}
Expand Up @@ -18,9 +18,9 @@ interface ImportOptions {

type ImportFunction = (to: string, opts: ImportOptions) => Promise<string | undefined>

export default (
export function createIndexedPkgImporter (
packageImportMethod?: 'auto' | 'hardlink' | 'copy' | 'clone' | 'clone-or-copy'
): ImportFunction => {
): ImportFunction {
const importPackage = createImportPackage(packageImportMethod)
return async (to, opts) => limitLinking(async () => importPackage(to, opts))
}
Expand Down
Expand Up @@ -19,10 +19,10 @@ baseLogger['globalWarn'] = globalWarn
jest.mock('@pnpm/logger', () => baseLogger)

// eslint-disable-next-line
import createImportPackage from '../lib/createImportPackage'
import { createIndexedPkgImporter } from '@pnpm/fs.indexed-pkg-importer'

test('packageImportMethod=auto: clone files by default', async () => {
const importPackage = createImportPackage('auto')
const importPackage = createIndexedPkgImporter('auto')
fsMock.promises.copyFile = jest.fn()
fsMock.promises.rename = jest.fn()
expect(await importPackage('project/package', {
Expand All @@ -46,7 +46,7 @@ test('packageImportMethod=auto: clone files by default', async () => {
})

test('packageImportMethod=auto: link files if cloning fails', async () => {
const importPackage = createImportPackage('auto')
const importPackage = createIndexedPkgImporter('auto')
fsMock.promises.copyFile = jest.fn(() => {
throw new Error('This file system does not support cloning')
})
Expand Down Expand Up @@ -80,7 +80,7 @@ test('packageImportMethod=auto: link files if cloning fails', async () => {
})

test('packageImportMethod=auto: link files if cloning fails and even hard linking fails but not with EXDEV error', async () => {
const importPackage = createImportPackage('auto')
const importPackage = createIndexedPkgImporter('auto')
fsMock.promises.copyFile = jest.fn(() => {
throw new Error('This file system does not support cloning')
})
Expand All @@ -105,7 +105,7 @@ test('packageImportMethod=auto: link files if cloning fails and even hard linkin
})

test('packageImportMethod=auto: chooses copying if cloning and hard linking is not possible', async () => {
const importPackage = createImportPackage('auto')
const importPackage = createIndexedPkgImporter('auto')
fsMock.promises.copyFile = jest.fn((src: string, dest: string, flags?: number) => {
if (flags === fsMock.constants.COPYFILE_FICLONE_FORCE) {
throw new Error('This file system does not support cloning')
Expand All @@ -127,7 +127,7 @@ test('packageImportMethod=auto: chooses copying if cloning and hard linking is n
})

test('packageImportMethod=hardlink: fall back to copying if hardlinking fails', async () => {
const importPackage = createImportPackage('hardlink')
const importPackage = createIndexedPkgImporter('hardlink')
fsMock.promises.link = jest.fn((src: string, dest: string) => {
if (dest.endsWith('license')) {
const err = new Error('')
Expand All @@ -153,7 +153,7 @@ test('packageImportMethod=hardlink: fall back to copying if hardlinking fails',
})

test('packageImportMethod=hardlink does not relink package from store if package.json is linked from the store', async () => {
const importPackage = createImportPackage('hardlink')
const importPackage = createIndexedPkgImporter('hardlink')
fsMock.promises.copyFile = jest.fn()
fsMock.promises.rename = jest.fn()
fsMock.promises.stat = jest.fn(() => ({ ino: 1 }))
Expand All @@ -169,7 +169,7 @@ test('packageImportMethod=hardlink does not relink package from store if package

test('packageImportMethod=hardlink relinks package from store if package.json is not linked from the store', async () => {
globalInfo.mockReset()
const importPackage = createImportPackage('hardlink')
const importPackage = createIndexedPkgImporter('hardlink')
fsMock.promises.copyFile = jest.fn()
fsMock.promises.rename = jest.fn()
let ino = 0
Expand All @@ -186,7 +186,7 @@ test('packageImportMethod=hardlink relinks package from store if package.json is
})

test('packageImportMethod=hardlink does not relink package from store if package.json is not present in the store', async () => {
const importPackage = createImportPackage('hardlink')
const importPackage = createIndexedPkgImporter('hardlink')
fsMock.promises.copyFile = jest.fn()
fsMock.promises.rename = jest.fn()
fsMock.promises.stat = jest.fn((file) => {
Expand All @@ -204,7 +204,7 @@ test('packageImportMethod=hardlink does not relink package from store if package

test('packageImportMethod=hardlink links packages when they are not found', async () => {
globalInfo.mockReset()
const importPackage = createImportPackage('hardlink')
const importPackage = createIndexedPkgImporter('hardlink')
fsMock.promises.copyFile = jest.fn()
fsMock.promises.rename = jest.fn()
fsMock.promises.stat = jest.fn((file) => {
Expand Down
@@ -1,11 +1,11 @@
import { promises as fs } from 'fs'
import path from 'path'
import { prepareEmpty } from '@pnpm/prepare'
import createImportPackage from '../lib/createImportPackage'
import { createIndexedPkgImporter } from '@pnpm/fs.indexed-pkg-importer'

test('importing a package with invalid files', async () => {
prepareEmpty()
const importPackage = createImportPackage('copy')
const importPackage = createIndexedPkgImporter('copy')
const target = path.resolve('target')
await importPackage(target, {
filesMap: {
Expand Down
19 changes: 19 additions & 0 deletions packages/fs.indexed-pkg-importer/tsconfig.json
@@ -0,0 +1,19 @@
{
"extends": "@pnpm/tsconfig",
"compilerOptions": {
"outDir": "lib",
"rootDir": "src"
},
"include": [
"src/**/*.ts",
"../../typings/**/*.d.ts"
],
"references": [
{
"path": "../../privatePackages/prepare"
},
{
"path": "../core-loggers"
}
]
}
8 changes: 8 additions & 0 deletions packages/fs.indexed-pkg-importer/tsconfig.lint.json
@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"include": [
"src/**/*.ts",
"test/**/*.ts",
"../../typings/**/*.d.ts"
]
}
15 changes: 15 additions & 0 deletions packages/plugin-commands-deploy/README.md
@@ -0,0 +1,15 @@
# @pnpm/plugin-commands-deploy

> Commands for deploy
[![npm version](https://img.shields.io/npm/v/@pnpm/plugin-commands-deploy.svg)](https://www.npmjs.com/package/@pnpm/plugin-commands-deploy)

## deploy

```sh
pnpm add @pnpm/plugin-commands-deploy
```

## License

MIT
1 change: 1 addition & 0 deletions packages/plugin-commands-deploy/jest.config.js
@@ -0,0 +1 @@
module.exports = require('../../jest.config.js')

0 comments on commit 316b51d

Please sign in to comment.