From 2e9790722aa2f981d547b62d8bbadb7a42795d50 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Fri, 4 Nov 2022 14:01:22 +0200 Subject: [PATCH] fix: use lexigraphical sorting in places where it matters (#5587) --- .changeset/smart-coats-jam.md | 7 +++++++ packages/find-packages/package.json | 1 + packages/find-packages/src/index.ts | 3 ++- packages/find-workspace-packages/package.json | 1 + packages/find-workspace-packages/src/index.ts | 3 ++- packages/hoist/package.json | 1 + packages/hoist/src/index.ts | 3 ++- packages/lockfile-file/package.json | 1 + packages/lockfile-file/src/sortLockfileKeys.ts | 6 ++---- pnpm-lock.yaml | 18 ++++++++++++++++++ 10 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 .changeset/smart-coats-jam.md diff --git a/.changeset/smart-coats-jam.md b/.changeset/smart-coats-jam.md new file mode 100644 index 0000000000..4f25a77904 --- /dev/null +++ b/.changeset/smart-coats-jam.md @@ -0,0 +1,7 @@ +--- +"@pnpm/find-workspace-packages": patch +"find-packages": patch +"@pnpm/hoist": patch +--- + +Use deterministic sorting. diff --git a/packages/find-packages/package.json b/packages/find-packages/package.json index fe0339b769..c6b7fcce5a 100644 --- a/packages/find-packages/package.json +++ b/packages/find-packages/package.json @@ -32,6 +32,7 @@ "dependencies": { "@pnpm/read-project-manifest": "workspace:*", "@pnpm/types": "workspace:*", + "@pnpm/util.lex-comparator": "1.0.0", "fast-glob": "^3.2.12", "p-filter": "^2.1.0" }, diff --git a/packages/find-packages/src/index.ts b/packages/find-packages/src/index.ts index eceb68112a..1e6885b0bb 100644 --- a/packages/find-packages/src/index.ts +++ b/packages/find-packages/src/index.ts @@ -1,6 +1,7 @@ import path from 'path' import { readExactProjectManifest } from '@pnpm/read-project-manifest' import { ProjectManifest } from '@pnpm/types' +import { lexCompare } from '@pnpm/util.lex-comparator' import fastGlob from 'fast-glob' import pFilter from 'p-filter' @@ -48,7 +49,7 @@ export async function findPackages (root: string, opts?: Options): Promise path.join(root, manifestPath)) .sort((path1, path2) => - path.dirname(path1).localeCompare(path.dirname(path2)) + lexCompare(path.dirname(path1), path.dirname(path2)) ) ), async manifestPath => { diff --git a/packages/find-workspace-packages/package.json b/packages/find-workspace-packages/package.json index 93aab15339..47d115dd09 100644 --- a/packages/find-workspace-packages/package.json +++ b/packages/find-workspace-packages/package.json @@ -32,6 +32,7 @@ "@pnpm/cli-utils": "workspace:*", "@pnpm/constants": "workspace:*", "@pnpm/types": "workspace:*", + "@pnpm/util.lex-comparator": "1.0.0", "find-packages": "workspace:*", "read-yaml-file": "^2.1.0" }, diff --git a/packages/find-workspace-packages/src/index.ts b/packages/find-workspace-packages/src/index.ts index 7cb177133e..a8fc7d588e 100644 --- a/packages/find-workspace-packages/src/index.ts +++ b/packages/find-workspace-packages/src/index.ts @@ -2,6 +2,7 @@ import path from 'path' import { packageIsInstallable } from '@pnpm/cli-utils' import { WORKSPACE_MANIFEST_FILENAME } from '@pnpm/constants' import { Project } from '@pnpm/types' +import { lexCompare } from '@pnpm/util.lex-comparator' import { findPackages } from 'find-packages' import readYamlFile from 'read-yaml-file' @@ -37,7 +38,7 @@ export async function findWorkspacePackagesNoCheck (workspaceRoot: string, opts? includeRoot: true, patterns, }) - pkgs.sort((pkg1: { dir: string }, pkg2: { dir: string }) => pkg1.dir.localeCompare(pkg2.dir)) + pkgs.sort((pkg1: { dir: string }, pkg2: { dir: string }) => lexCompare(pkg1.dir, pkg2.dir)) return pkgs } diff --git a/packages/hoist/package.json b/packages/hoist/package.json index 8324186b4d..8b952b9d26 100644 --- a/packages/hoist/package.json +++ b/packages/hoist/package.json @@ -47,6 +47,7 @@ "@pnpm/matcher": "workspace:*", "@pnpm/symlink-dependency": "workspace:*", "@pnpm/types": "workspace:*", + "@pnpm/util.lex-comparator": "1.0.0", "dependency-path": "workspace:*", "ramda": "npm:@pnpm/ramda@0.28.1" }, diff --git a/packages/hoist/src/index.ts b/packages/hoist/src/index.ts index 3c4e2f1fdf..5a2463859e 100644 --- a/packages/hoist/src/index.ts +++ b/packages/hoist/src/index.ts @@ -10,6 +10,7 @@ import { logger } from '@pnpm/logger' import { createMatcher } from '@pnpm/matcher' import { symlinkDependency } from '@pnpm/symlink-dependency' import { HoistedDependencies } from '@pnpm/types' +import { lexCompare } from '@pnpm/util.lex-comparator' import * as dp from 'dependency-path' const hoistLogger = logger('hoist') @@ -171,7 +172,7 @@ async function hoistGraph ( // sort by depth and then alphabetically .sort((a, b) => { const depthDiff = a.depth - b.depth - return depthDiff === 0 ? a.depPath.localeCompare(b.depPath) : depthDiff + return depthDiff === 0 ? lexCompare(a.depPath, b.depPath) : depthDiff }) // build the alias map and the id map .forEach((depNode) => { diff --git a/packages/lockfile-file/package.json b/packages/lockfile-file/package.json index 9c88110382..e98c3ef8b5 100644 --- a/packages/lockfile-file/package.json +++ b/packages/lockfile-file/package.json @@ -52,6 +52,7 @@ "@pnpm/lockfile-types": "workspace:*", "@pnpm/merge-lockfile-changes": "workspace:*", "@pnpm/types": "workspace:*", + "@pnpm/util.lex-comparator": "1.0.0", "@zkochan/rimraf": "^2.1.2", "comver-to-semver": "^1.0.0", "dependency-path": "workspace:*", diff --git a/packages/lockfile-file/src/sortLockfileKeys.ts b/packages/lockfile-file/src/sortLockfileKeys.ts index 2517c23b4a..382ff5435b 100644 --- a/packages/lockfile-file/src/sortLockfileKeys.ts +++ b/packages/lockfile-file/src/sortLockfileKeys.ts @@ -1,3 +1,4 @@ +import { lexCompare } from '@pnpm/util.lex-comparator' import sortKeys from 'sort-keys' import { LockfileFile } from './write' @@ -53,10 +54,7 @@ function compareWithPriority (priority: Record, left: string, ri if (leftPriority && rightPriority) return leftPriority - rightPriority if (leftPriority) return -1 if (rightPriority) return 1 - // We want deterministic sorting, so we can't use .localCompare here. - // comparing strings with < and > will produce the same result on each machine. - // An alternative solution could be to use a specific culture for compare, using Intl.Collator - return left < right ? -1 : (left > right ? 1 : 0) + return lexCompare(left, right) } export function sortLockfileKeys (lockfile: LockfileFile) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 34db35e2f6..0cb255773e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1314,6 +1314,9 @@ importers: '@pnpm/types': specifier: workspace:* version: link:../types + '@pnpm/util.lex-comparator': + specifier: 1.0.0 + version: 1.0.0 fast-glob: specifier: ^3.2.12 version: 3.2.12 @@ -1349,6 +1352,9 @@ importers: '@pnpm/types': specifier: workspace:* version: link:../types + '@pnpm/util.lex-comparator': + specifier: 1.0.0 + version: 1.0.0 find-packages: specifier: workspace:* version: link:../find-packages @@ -1726,6 +1732,9 @@ importers: '@pnpm/types': specifier: workspace:* version: link:../types + '@pnpm/util.lex-comparator': + specifier: 1.0.0 + version: 1.0.0 dependency-path: specifier: workspace:* version: link:../dependency-path @@ -2020,6 +2029,9 @@ importers: '@pnpm/types': specifier: workspace:* version: link:../types + '@pnpm/util.lex-comparator': + specifier: 1.0.0 + version: 1.0.0 '@zkochan/rimraf': specifier: ^2.1.2 version: 2.1.2 @@ -7836,6 +7848,11 @@ packages: engines: {node: '>=14.6'} dev: true + /@pnpm/util.lex-comparator/1.0.0: + resolution: {integrity: sha512-3aBQPHntVgk5AweBWZn+1I/fqZ9krK/w01197aYVkAJQGftb+BVWgEepxY5GChjSW12j52XX+CmfynYZ/p0DFQ==} + engines: {node: '>=12.22.0'} + dev: false + /@pnpm/which-version-is-pinned/4.0.0: resolution: {integrity: sha512-XqZqdxgX7vqxiMX+REsN6lfZ9TR2FQhhaaClA6ymFAVjhuMzJidDDVibqAx5nlfoSqeBklJEZxYXYnU7LjghlA==} engines: {node: '>=14.6'} @@ -16967,6 +16984,7 @@ time: /@pnpm/registry-mock/3.1.0: '2022-10-13T19:59:17.408Z' /@pnpm/semver-diff/1.1.0: '2021-11-16T12:40:59.941Z' /@pnpm/tabtab/0.1.2: '2021-03-05T17:31:19.932Z' + /@pnpm/util.lex-comparator/1.0.0: '2022-11-04T01:03:46.134Z' /@types/adm-zip/0.4.34: '2021-04-04T18:01:23.318Z' /@types/archy/0.0.32: '2021-07-06T18:11:33.301Z' /@types/byline/4.2.33: '2021-07-06T18:22:06.440Z'