Skip to content

Commit 5a937c6

Browse files
committed
Clean up in prep for usint eslint fixer
1 parent 5fe340f commit 5a937c6

File tree

3 files changed

+76
-18
lines changed

3 files changed

+76
-18
lines changed

packages/meta-updater/src/formats.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ import { equals } from "ramda";
44
import yaml from "yaml";
55

66
export const formats = {
7+
/**
8+
* A format that today we just use for .pre-commit-config.yaml files. This is a yaml file, but we
9+
* need to preserve comments, so we use the `yaml` library's document representation instead of
10+
* parsing it into a plain js object.
11+
*/
712
[".yaml"]: createFormat({
813
async read({ resolvedPath }) {
914
return yaml.parseDocument(await readFile(resolvedPath, "utf-8")).clone();

packages/meta-updater/src/getPackageDeps.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@ import normalizePath from "normalize-path";
22
import path from "path";
33
import { Lockfile } from "@pnpm/lockfile-file";
44

5+
/**
6+
* Get the dependencies of the given package from the pnpm lockfile.
7+
* @param workspaceDir The root of the workspace
8+
* @param packageDir The directory of the package whose dependencies we are
9+
* retrieving
10+
* @param pnpmLockfile The parsed pnpm lockfile
11+
* @returns A map of package names to package specs for the dependencies of the
12+
* given package
13+
*/
514
export function getPackageDeps(
615
workspaceDir: string,
716
packageDir: string,

packages/meta-updater/src/updatePreCommit.ts

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import { Document, ParsedNode } from "yaml";
33
import { Context } from "./Context";
44
import { getPackageDeps } from "./getPackageDeps";
55

6+
/**
7+
* Subset of the .pre-commit-config.yaml schema that we care about.
8+
*/
69
interface PreCommitConfig {
710
repos: {
811
hooks: {
@@ -14,15 +17,19 @@ interface PreCommitConfig {
1417
}
1518

1619
/**
17-
* Given a tsconfig.json, update it to match our conventions. This function is
18-
* called by the pnpm `meta-updater` plugin either to check if the tsconfig.json
19-
* is up to date or to update it, depending on flags.
20+
* Given a .pre-commit-config.yaml, update it to ensure that the versions of our
21+
* hooks match the corresponding package versions in package.json. This
22+
* function is called by the pnpm `meta-updater` plugin either to check if the
23+
* .pre-commit-config.yaml is up to date or to update it, depending on flags.
2024
* @param context Contains context such as workspace dir and parsed pnpm
2125
* lockfile
22-
* @param rawInput The input tsconfig.json that should be checked / updated
26+
* @param rawInput The input .pre-commit-config.yaml that should be checked /
27+
* updated. This is a parsed yaml document in the `yaml` library's document
28+
* representation; not a plain js object like you'd get from a json parser. We
29+
* need it like this so that we can preserve comments.
2330
* @param options Extra information provided by pnpm; mostly just the directory
24-
* of the package whose tsconfig.json we are updating
25-
* @returns The updated tsconfig.json
31+
* of the package whose .pre-commit-config.yaml we are updating
32+
* @returns The updated .pre-commit-config.yaml
2633
*/
2734
export async function updatePreCommit(
2835
{ workspaceDir, pnpmLockfile }: Context,
@@ -32,36 +39,73 @@ export async function updatePreCommit(
3239
if (rawInput == null) {
3340
return null;
3441
}
35-
/** Directory of the package whose tsconfig.json we are updating */
42+
/** Directory of the package whose .pre-commit-config.yaml we are updating */
3643
const packageDir = options.dir;
3744

3845
if (packageDir !== workspaceDir) {
3946
throw new Error("updatePreCommit should only be called on root");
4047
}
4148

4249
const deps = getPackageDeps(workspaceDir, packageDir, pnpmLockfile);
43-
const prettierVersion = deps["prettier"];
4450

45-
const prettierHookIndex = (rawInput.toJS() as PreCommitConfig).repos
51+
updateHook(deps, rawInput, "prettier", (name) => name === "prettier");
52+
53+
return rawInput;
54+
}
55+
56+
/**
57+
* Updates the additional_dependencies of a hook in a .pre-commit-config.yaml to
58+
* match the versions from the lockfile.
59+
* @param deps Dependencies of the package whose .pre-commit-config.yaml we are
60+
* updating
61+
* @param rawInput The input .pre-commit-config.yaml that should be checked /
62+
* updated
63+
* @param hookId The id of the hook to update
64+
* @param packageMatcher A function that returns true if the given package name
65+
* should be added to the hook's additional_dependencies
66+
*/
67+
function updateHook(
68+
deps: { [x: string]: string },
69+
rawInput: Document<ParsedNode>,
70+
hookId: string,
71+
packageMatcher: (name: string) => boolean,
72+
) {
73+
const packages = Object.entries(deps).filter(([name]) =>
74+
packageMatcher(name),
75+
);
76+
77+
// Find the hook in the .pre-commit-config.yaml. Easier to grab the indices
78+
// from the raw js representation so that we can just use `setIn` to update
79+
// the hook
80+
const desiredHooks = (rawInput.toJS() as PreCommitConfig).repos
4681
.flatMap(({ hooks }, repoIndex) =>
4782
hooks.map((hook, hookIndex) => ({ hook, repoIndex, hookIndex })),
4883
)
49-
.filter(({ hook }) => hook.id === "prettier");
84+
.filter(({ hook }) => hook.id === hookId);
5085

51-
if (prettierHookIndex.length === 0) {
52-
throw new Error("No prettier hook found");
86+
if (desiredHooks.length === 0) {
87+
throw new Error(`No ${hookId} hook found`);
5388
}
5489

55-
if (prettierHookIndex.length > 1) {
56-
throw new Error("Multiple prettier hooks found");
90+
if (desiredHooks.length > 1) {
91+
throw new Error(`Multiple ${hookId} hooks found`);
5792
}
5893

59-
const { repoIndex, hookIndex } = prettierHookIndex[0];
94+
const { repoIndex, hookIndex } = desiredHooks[0];
6095

6196
rawInput.setIn(
6297
["repos", repoIndex, "hooks", hookIndex, "additional_dependencies"],
63-
rawInput.createNode([`prettier@${prettierVersion}`]),
98+
rawInput.createNode(
99+
packages
100+
.map(([name, version]) => {
101+
if (version.includes("(")) {
102+
// pnpm includes the integrity hash in the version, which we don't
103+
// need here
104+
version = version.slice(0, version.indexOf("("));
105+
}
106+
return `${name}@${version}`;
107+
})
108+
.sort(),
109+
),
64110
);
65-
66-
return rawInput;
67111
}

0 commit comments

Comments
 (0)