workspace-tools 0.15.1 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.json CHANGED
@@ -2,7 +2,82 @@
2
2
  "name": "workspace-tools",
3
3
  "entries": [
4
4
  {
5
- "date": "Wed, 19 May 2021 21:05:04 GMT",
5
+ "date": "Thu, 02 Dec 2021 17:11:04 GMT",
6
+ "tag": "workspace-tools_v0.17.0",
7
+ "version": "0.17.0",
8
+ "comments": {
9
+ "minor": [
10
+ {
11
+ "author": "riacarmin@microsoft.com",
12
+ "package": "workspace-tools",
13
+ "comment": "Implements NPM workspaces support to parseLockFile utility.",
14
+ "commit": "0d9b3bd5c091e238d302f4a6912692e2eda95385"
15
+ }
16
+ ]
17
+ }
18
+ },
19
+ {
20
+ "date": "Thu, 21 Oct 2021 20:01:33 GMT",
21
+ "tag": "workspace-tools_v0.16.2",
22
+ "version": "0.16.2",
23
+ "comments": {
24
+ "none": [
25
+ {
26
+ "author": "elcraig@microsoft.com",
27
+ "package": "workspace-tools",
28
+ "comment": "Update beachball and add ignorePatterns",
29
+ "commit": "1aca866df2443581ce221c08b8e783a7054fcd7d"
30
+ }
31
+ ]
32
+ }
33
+ },
34
+ {
35
+ "date": "Thu, 03 Jun 2021 20:23:22 GMT",
36
+ "tag": "workspace-tools_v0.16.2",
37
+ "version": "0.16.2",
38
+ "comments": {
39
+ "patch": [
40
+ {
41
+ "comment": "get the right default remote branch",
42
+ "author": "kchau@microsoft.com",
43
+ "commit": "cb3c26d432f838805190f9afb65181f682c0145a",
44
+ "package": "workspace-tools"
45
+ }
46
+ ]
47
+ }
48
+ },
49
+ {
50
+ "date": "Thu, 27 May 2021 20:04:05 GMT",
51
+ "tag": "workspace-tools_v0.16.1",
52
+ "version": "0.16.1",
53
+ "comments": {
54
+ "patch": [
55
+ {
56
+ "comment": "getting rid of console logs from the library",
57
+ "author": "kchau@microsoft.com",
58
+ "commit": "7f47e421c14b9122d19f848f8039ae266c55e692",
59
+ "package": "workspace-tools"
60
+ }
61
+ ]
62
+ }
63
+ },
64
+ {
65
+ "date": "Tue, 25 May 2021 21:47:27 GMT",
66
+ "tag": "workspace-tools_v0.16.0",
67
+ "version": "0.16.0",
68
+ "comments": {
69
+ "minor": [
70
+ {
71
+ "comment": "Fix #24: Add support for different upstream branches",
72
+ "author": "dannyvv@microsoft.com",
73
+ "commit": "83546ce7c0ff54f588ad1fca54f2620d8f071708",
74
+ "package": "workspace-tools"
75
+ }
76
+ ]
77
+ }
78
+ },
79
+ {
80
+ "date": "Wed, 19 May 2021 21:05:10 GMT",
6
81
  "tag": "workspace-tools_v0.15.1",
7
82
  "version": "0.15.1",
8
83
  "comments": {
package/CHANGELOG.md CHANGED
@@ -1,12 +1,44 @@
1
1
  # Change Log - workspace-tools
2
2
 
3
- This log was last generated on Wed, 19 May 2021 21:05:04 GMT and should not be manually modified.
3
+ This log was last generated on Thu, 02 Dec 2021 17:11:04 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 0.17.0
8
+
9
+ Thu, 02 Dec 2021 17:11:04 GMT
10
+
11
+ ### Minor changes
12
+
13
+ - Implements NPM workspaces support to parseLockFile utility. (riacarmin@microsoft.com)
14
+
15
+ ## 0.16.2
16
+
17
+ Thu, 03 Jun 2021 20:23:22 GMT
18
+
19
+ ### Patches
20
+
21
+ - get the right default remote branch (kchau@microsoft.com)
22
+
23
+ ## 0.16.1
24
+
25
+ Thu, 27 May 2021 20:04:05 GMT
26
+
27
+ ### Patches
28
+
29
+ - getting rid of console logs from the library (kchau@microsoft.com)
30
+
31
+ ## 0.16.0
32
+
33
+ Tue, 25 May 2021 21:47:27 GMT
34
+
35
+ ### Minor changes
36
+
37
+ - Fix #24: Add support for different upstream branches (dannyvv@microsoft.com)
38
+
7
39
  ## 0.15.1
8
40
 
9
- Wed, 19 May 2021 21:05:04 GMT
41
+ Wed, 19 May 2021 21:05:10 GMT
10
42
 
11
43
  ### Patches
12
44
 
package/README.md CHANGED
@@ -2,10 +2,11 @@
2
2
 
3
3
  A collection of tools that are useful in a git-controlled monorepo that is managed by one of these software:
4
4
 
5
+ - lerna
6
+ - npm workspaces
7
+ - pnpm workspaces
5
8
  - rush
6
9
  - yarn workspaces
7
- - pnpm workspaces
8
- - lerna
9
10
 
10
11
  # Environment Variables
11
12
 
@@ -17,7 +18,7 @@ default node.js maxBuffer of 1MB)
17
18
  ## PREFERRED_WORKSPACE_MANAGER
18
19
 
19
20
  Sometimes multiple package manager files are checked in. It is necessary to hint to `workspace-tools` which manager
20
- is used: `yarn`, `pnpm`, `rush`, or `lerna`
21
+ is used: `npm`, `yarn`, `pnpm`, `rush`, or `lerna`
21
22
 
22
23
  # Contributing
23
24
 
@@ -1,3 +1,12 @@
1
1
  module.exports = {
2
2
  scope: ["!src/__fixtures__/**/*"],
3
+ ignorePatterns: [
4
+ ".github/**",
5
+ ".prettierrc",
6
+ "jest.config.js",
7
+ "src/__fixtures__/**",
8
+ "src/__tests__/**",
9
+ // This prevents dependabot from being blocked by change file requirements for lock file-only changes
10
+ "yarn.lock",
11
+ ],
3
12
  };
@@ -18,7 +18,7 @@ describe("getChangedPackages()", () => {
18
18
  const newFile = path_1.default.join(root, "packages/package-a/footest.txt");
19
19
  fs_1.default.writeFileSync(newFile, "hello foo test");
20
20
  // act
21
- const changedPkgs = getChangedPackages_1.getChangedPackages(root, "master");
21
+ const changedPkgs = getChangedPackages_1.getChangedPackages(root, "main");
22
22
  // assert
23
23
  expect(changedPkgs).toContain("package-a");
24
24
  });
@@ -28,7 +28,7 @@ describe("getChangedPackages()", () => {
28
28
  const newFile = path_1.default.join(root, "packages/package-a/footest.txt");
29
29
  fs_1.default.writeFileSync(newFile, "hello foo test");
30
30
  // act
31
- const changedPkgs = getChangedPackages_1.getChangedPackages(root, "master");
31
+ const changedPkgs = getChangedPackages_1.getChangedPackages(root, "main");
32
32
  // assert
33
33
  expect(changedPkgs).toEqual(["package-a"]);
34
34
  });
@@ -38,7 +38,7 @@ describe("getChangedPackages()", () => {
38
38
  const newFile = path_1.default.join(root, "packages/package-a/src/index.ts");
39
39
  fs_1.default.writeFileSync(newFile, "hello foo test");
40
40
  // act
41
- const changedPkgs = getChangedPackages_1.getChangedPackages(root, "master");
41
+ const changedPkgs = getChangedPackages_1.getChangedPackages(root, "main");
42
42
  // assert
43
43
  expect(changedPkgs).toContain("package-a");
44
44
  });
@@ -48,7 +48,7 @@ describe("getChangedPackages()", () => {
48
48
  const newFile = path_1.default.join(root, "packages/package-a/src/index.ts");
49
49
  fs_1.default.writeFileSync(newFile, "hello foo test");
50
50
  // act
51
- const changedPkgs = getChangedPackages_1.getChangedPackages(root, "master");
51
+ const changedPkgs = getChangedPackages_1.getChangedPackages(root, "main");
52
52
  // assert
53
53
  expect(changedPkgs).toEqual(["package-a"]);
54
54
  });
@@ -59,7 +59,7 @@ describe("getChangedPackages()", () => {
59
59
  fs_1.default.writeFileSync(newFile, "hello foo test");
60
60
  git_1.git(["add", newFile], { cwd: root });
61
61
  // act
62
- const changedPkgs = getChangedPackages_1.getChangedPackages(root, "master");
62
+ const changedPkgs = getChangedPackages_1.getChangedPackages(root, "main");
63
63
  // assert
64
64
  expect(changedPkgs).toContain("package-a");
65
65
  });
@@ -70,7 +70,7 @@ describe("getChangedPackages()", () => {
70
70
  fs_1.default.writeFileSync(newFile, "hello foo test");
71
71
  git_1.git(["add", newFile], { cwd: root });
72
72
  // act
73
- const changedPkgs = getChangedPackages_1.getChangedPackages(root, "master");
73
+ const changedPkgs = getChangedPackages_1.getChangedPackages(root, "main");
74
74
  // assert
75
75
  expect(changedPkgs).toEqual(["package-a"]);
76
76
  });
@@ -82,7 +82,7 @@ describe("getChangedPackages()", () => {
82
82
  git_1.git(["checkout", "-b", "newbranch"], { cwd: root });
83
83
  git_1.stageAndCommit(["add", newFile], "test commit", root);
84
84
  // act
85
- const changedPkgs = getChangedPackages_1.getChangedPackages(root, "master");
85
+ const changedPkgs = getChangedPackages_1.getChangedPackages(root, "main");
86
86
  // assert
87
87
  expect(changedPkgs).toContain("package-a");
88
88
  });
@@ -94,10 +94,23 @@ describe("getChangedPackages()", () => {
94
94
  git_1.git(["checkout", "-b", "newbranch"], { cwd: root });
95
95
  git_1.stageAndCommit(["add", newFile], "test commit", root);
96
96
  // act
97
- const changedPkgs = getChangedPackages_1.getChangedPackages(root, "master");
97
+ const changedPkgs = getChangedPackages_1.getChangedPackages(root, "main");
98
98
  // assert
99
99
  expect(changedPkgs).toEqual(["package-a"]);
100
100
  });
101
+ it("can detect changes inside a file that has been committed in a different branch using default remote", () => {
102
+ // arrange
103
+ const root = setupFixture_1.setupFixture("monorepo");
104
+ setupFixture_1.setupLocalRemote(root, "origin", "basic");
105
+ const newFile = path_1.default.join(root, "packages/package-a/footest.txt");
106
+ fs_1.default.writeFileSync(newFile, "hello foo test");
107
+ git_1.git(["checkout", "-b", "newbranch"], { cwd: root });
108
+ git_1.stageAndCommit(["add", newFile], "test commit", root);
109
+ // act
110
+ const changedPkgs = getChangedPackages_1.getChangedPackages(root, undefined);
111
+ // assert
112
+ expect(changedPkgs).toContain("package-a");
113
+ });
101
114
  it("can ignore glob patterns in detecting changes", () => {
102
115
  // arrange
103
116
  const root = setupFixture_1.setupFixture("monorepo");
@@ -105,7 +118,7 @@ describe("getChangedPackages()", () => {
105
118
  fs_1.default.writeFileSync(newFile, "hello foo test");
106
119
  git_1.git(["add", newFile], { cwd: root });
107
120
  // act
108
- const changedPkgs = getChangedPackages_1.getChangedPackages(root, "master", ["packages/package-a/*"]);
121
+ const changedPkgs = getChangedPackages_1.getChangedPackages(root, "main", ["packages/package-a/*"]);
109
122
  // assert
110
123
  expect(changedPkgs).toEqual([]);
111
124
  });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const setupFixture_1 = require("../helpers/setupFixture");
4
+ const git_1 = require("../git");
5
+ describe("getDefaultRemote()", () => {
6
+ afterAll(() => {
7
+ setupFixture_1.cleanupFixtures();
8
+ });
9
+ it("is origin in the default test repo", () => {
10
+ // arrange
11
+ const cwd = setupFixture_1.setupFixture("basic");
12
+ // act
13
+ const remote = git_1.getDefaultRemote(cwd);
14
+ // assert
15
+ expect(remote).toBe("origin");
16
+ });
17
+ it("is myMain when default branch is different", () => {
18
+ // arrange
19
+ const cwd = setupFixture_1.setupFixture("basic");
20
+ setupFixture_1.setupLocalRemote(cwd, "myRemote", "basic");
21
+ // act
22
+ const remote = git_1.getDefaultRemote(cwd);
23
+ // assert
24
+ expect(remote).toBe("myRemote");
25
+ });
26
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const setupFixture_1 = require("../helpers/setupFixture");
4
+ const git_1 = require("../git");
5
+ describe("getDefaultBranch()", () => {
6
+ afterAll(() => {
7
+ setupFixture_1.cleanupFixtures();
8
+ });
9
+ it("is main in the default test repo", () => {
10
+ // arrange
11
+ const cwd = setupFixture_1.setupFixture("basic");
12
+ // act
13
+ const branch = git_1.getDefaultBranch(cwd);
14
+ // assert
15
+ expect(branch).toBe("main");
16
+ });
17
+ it("is myMain when default branch is different", () => {
18
+ // arrange
19
+ const cwd = setupFixture_1.setupFixture("basic");
20
+ git_1.git(['config', 'init.defaultBranch', 'myMain'], { cwd });
21
+ // act
22
+ const branch = git_1.getDefaultBranch(cwd);
23
+ // assert
24
+ expect(branch).toBe("myMain");
25
+ });
26
+ });
@@ -2,22 +2,39 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const setupFixture_1 = require("../helpers/setupFixture");
4
4
  const lockfile_1 = require("../lockfile");
5
+ const ERROR_MESSAGES = {
6
+ NO_LOCK: "You do not have yarn.lock, pnpm-lock.yaml or package-lock.json. Please use one of these package managers.",
7
+ UNSUPPORTED: "Your package-lock.json version is not supported: lockfileVersion is 1. You need npm version 7 or above and package-lock version 2 or above. Please, upgrade npm or choose a different package manager.",
8
+ };
5
9
  describe("parseLockFile()", () => {
10
+ // General
11
+ it("throws if it cannot find lock file", async () => {
12
+ const packageRoot = await setupFixture_1.setupFixture("basic-without-lock-file");
13
+ await expect(lockfile_1.parseLockFile(packageRoot)).rejects.toThrow(ERROR_MESSAGES.NO_LOCK);
14
+ });
15
+ // NPM
16
+ it("parses package-lock.json file when it is found", async () => {
17
+ const packageRoot = await setupFixture_1.setupFixture("monorepo-npm");
18
+ const parsedLockeFile = await lockfile_1.parseLockFile(packageRoot);
19
+ expect(parsedLockeFile).toHaveProperty("type", "success");
20
+ });
21
+ it("throws if npm version is unsupported", async () => {
22
+ const packageRoot = await setupFixture_1.setupFixture("monorepo-npm-unsupported");
23
+ await expect(lockfile_1.parseLockFile(packageRoot)).rejects.toThrow(ERROR_MESSAGES.UNSUPPORTED);
24
+ });
25
+ // Yarn
6
26
  it("parses yarn.lock file when it is found", async () => {
7
27
  const packageRoot = await setupFixture_1.setupFixture("basic");
8
28
  const parsedLockeFile = await lockfile_1.parseLockFile(packageRoot);
9
29
  expect(parsedLockeFile).toHaveProperty("type", "success");
10
30
  });
11
- it("throws if it cannot find a yarn.lock file", async () => {
12
- const packageRoot = await setupFixture_1.setupFixture("basic-without-lock-file");
13
- await expect(lockfile_1.parseLockFile(packageRoot)).rejects.toThrow("You do not have either yarn.lock nor pnpm-lock.yaml. Please use one of these package managers");
14
- });
15
31
  it("parses combined ranges in yarn.lock", async () => {
16
32
  const packageRoot = await setupFixture_1.setupFixture("basic-yarn");
17
33
  const parsedLockeFile = await lockfile_1.parseLockFile(packageRoot);
18
34
  expect(parsedLockeFile.object["@babel/code-frame@^7.0.0"].version).toBe(parsedLockeFile.object["@babel/code-frame@^7.8.3"].version);
19
35
  });
20
- it("parses pnpm-lock.yaml properly", async () => {
36
+ // PNPM
37
+ it("parses pnpm-lock.yaml file when it is found", async () => {
21
38
  const packageRoot = await setupFixture_1.setupFixture("basic-pnpm");
22
39
  const parsedLockeFile = await lockfile_1.parseLockFile(packageRoot);
23
40
  expect(Object.keys(parsedLockeFile.object["yargs@16.2.0"].dependencies)).toContain("cliui");
@@ -17,7 +17,7 @@ function getPackageInfos(cwd) {
17
17
  }
18
18
  catch (e) {
19
19
  // Pass, the package.json is invalid
20
- console.warn(`Invalid package.json file detected ${packageJsonPath}: `, e);
20
+ throw new Error(`Invalid package.json file detected ${packageJsonPath}: ${e.message}`);
21
21
  }
22
22
  });
23
23
  return packageInfos;
package/lib/git.d.ts CHANGED
@@ -23,25 +23,25 @@ export declare function gitFailFast(args: string[], options?: {
23
23
  cwd: string;
24
24
  maxBuffer?: number;
25
25
  }): void;
26
- export declare function getUntrackedChanges(cwd: string): string[] | undefined;
26
+ export declare function getUntrackedChanges(cwd: string): string[];
27
27
  export declare function fetchRemote(remote: string, cwd: string): void;
28
28
  export declare function fetchRemoteBranch(remote: string, remoteBranch: string, cwd: string): void;
29
29
  /**
30
30
  * Gets all the changes that have not been staged yet
31
31
  * @param cwd
32
32
  */
33
- export declare function getUnstagedChanges(cwd: string): string[] | undefined;
34
- export declare function getChanges(branch: string, cwd: string): string[] | undefined;
33
+ export declare function getUnstagedChanges(cwd: string): string[];
34
+ export declare function getChanges(branch: string, cwd: string): string[];
35
35
  /**
36
36
  * Gets all the changes between the branch and the merge-base
37
37
  * @param branch
38
38
  * @param cwd
39
39
  */
40
40
  export declare function getBranchChanges(branch: string, cwd: string): string[];
41
- export declare function getChangesBetweenRefs(fromRef: string, toRef: string, options: string[], pattern: string, cwd: string): string[] | undefined;
42
- export declare function getStagedChanges(cwd: string): string[] | undefined;
43
- export declare function getRecentCommitMessages(branch: string, cwd: string): string[] | undefined;
44
- export declare function getUserEmail(cwd: string): string | null | undefined;
41
+ export declare function getChangesBetweenRefs(fromRef: string, toRef: string, options: string[], pattern: string, cwd: string): string[];
42
+ export declare function getStagedChanges(cwd: string): string[];
43
+ export declare function getRecentCommitMessages(branch: string, cwd: string): string[];
44
+ export declare function getUserEmail(cwd: string): string | null;
45
45
  export declare function getBranchName(cwd: string): string | null;
46
46
  export declare function getFullBranchRef(branch: string, cwd: string): string | null;
47
47
  export declare function getShortBranchName(fullBranchRef: string, cwd: string): string | null;
@@ -62,6 +62,7 @@ export declare function parseRemoteBranch(branch: string): {
62
62
  remoteBranch: string;
63
63
  };
64
64
  export declare function getDefaultRemoteBranch(branch: string | undefined, cwd: string): string;
65
+ export declare function getDefaultBranch(cwd: string): string;
65
66
  export declare function getDefaultRemote(cwd: string): string;
66
67
  export declare function listAllTrackedFiles(patterns: string[], cwd: string): string[];
67
68
  export {};
package/lib/git.js CHANGED
@@ -61,10 +61,10 @@ exports.git = git;
61
61
  function gitFailFast(args, options) {
62
62
  const gitResult = git(args, options);
63
63
  if (!gitResult.success) {
64
- console.error(`CRITICAL ERROR: running git command: git ${args.join(" ")}!`);
65
- console.error(gitResult.stdout && gitResult.stdout.toString().trimRight());
66
- console.error(gitResult.stderr && gitResult.stderr.toString().trimRight());
67
- process.exit(1);
64
+ process.exitCode = 1;
65
+ throw new Error(`CRITICAL ERROR: running git command: git ${args.join(" ")}!
66
+ ${gitResult.stdout && gitResult.stdout.toString().trimRight()}
67
+ ${gitResult.stderr && gitResult.stderr.toString().trimRight()}`);
68
68
  }
69
69
  }
70
70
  exports.gitFailFast = gitFailFast;
@@ -92,7 +92,7 @@ function getUntrackedChanges(cwd) {
92
92
  return untracked;
93
93
  }
94
94
  catch (e) {
95
- console.error("Cannot gather information about changes: ", e.message);
95
+ throw new Error(`Cannot gather information about untracked changes: ${e.message}`);
96
96
  }
97
97
  }
98
98
  exports.getUntrackedChanges = getUntrackedChanges;
@@ -119,7 +119,7 @@ function getUnstagedChanges(cwd) {
119
119
  return processGitOutput(git(["--no-pager", "diff", "--name-only", "--relative"], { cwd }));
120
120
  }
121
121
  catch (e) {
122
- console.error("Cannot gather information about changes: ", e.message);
122
+ throw new Error(`Cannot gather information about unstaged changes: ${e.message}`);
123
123
  }
124
124
  }
125
125
  exports.getUnstagedChanges = getUnstagedChanges;
@@ -128,7 +128,7 @@ function getChanges(branch, cwd) {
128
128
  return processGitOutput(git(["--no-pager", "diff", "--relative", "--name-only", branch + "..."], { cwd }));
129
129
  }
130
130
  catch (e) {
131
- console.error("Cannot gather information about changes: ", e.message);
131
+ throw new Error(`Cannot gather information about changes: ${e.message}`);
132
132
  }
133
133
  }
134
134
  exports.getChanges = getChanges;
@@ -142,7 +142,7 @@ function getBranchChanges(branch, cwd) {
142
142
  return processGitOutput(git(["--no-pager", "diff", "--name-only", "--relative", branch + "..."], { cwd }));
143
143
  }
144
144
  catch (e) {
145
- throw new Error(e.message);
145
+ throw new Error(`Cannot gather information about branch changes: ${e.message}`);
146
146
  }
147
147
  }
148
148
  exports.getBranchChanges = getBranchChanges;
@@ -153,7 +153,7 @@ function getChangesBetweenRefs(fromRef, toRef, options, pattern, cwd) {
153
153
  }));
154
154
  }
155
155
  catch (e) {
156
- console.error("Cannot gather information about changes: ", e.message);
156
+ throw new Error(`Cannot gather information about change between refs changes (${fromRef} to ${toRef}): ${e.message}`);
157
157
  }
158
158
  }
159
159
  exports.getChangesBetweenRefs = getChangesBetweenRefs;
@@ -162,7 +162,7 @@ function getStagedChanges(cwd) {
162
162
  return processGitOutput(git(["--no-pager", "diff", "--relative", "--staged", "--name-only"], { cwd }));
163
163
  }
164
164
  catch (e) {
165
- console.error("Cannot gather information about changes: ", e.message);
165
+ throw new Error(`Cannot gather information about staged changes: ${e.message}`);
166
166
  }
167
167
  }
168
168
  exports.getStagedChanges = getStagedChanges;
@@ -177,7 +177,7 @@ function getRecentCommitMessages(branch, cwd) {
177
177
  return lines.map((line) => line.trim());
178
178
  }
179
179
  catch (e) {
180
- console.error("Cannot gather information about recent commits: ", e.message);
180
+ throw new Error(`Cannot gather information about recent commits: ${e.message}`);
181
181
  }
182
182
  }
183
183
  exports.getRecentCommitMessages = getRecentCommitMessages;
@@ -190,7 +190,7 @@ function getUserEmail(cwd) {
190
190
  return results.stdout;
191
191
  }
192
192
  catch (e) {
193
- console.error("Cannot gather information about user.email: ", e.message);
193
+ throw new Error(`Cannot gather information about user.email: ${e.message}`);
194
194
  }
195
195
  }
196
196
  exports.getUserEmail = getUserEmail;
@@ -202,7 +202,7 @@ function getBranchName(cwd) {
202
202
  }
203
203
  }
204
204
  catch (e) {
205
- console.error("Cannot get branch name: ", e.message);
205
+ throw new Error(`Cannot get branch name: ${e.message}`);
206
206
  }
207
207
  return null;
208
208
  }
@@ -233,7 +233,7 @@ function getCurrentHash(cwd) {
233
233
  }
234
234
  }
235
235
  catch (e) {
236
- console.error("Cannot get current git hash");
236
+ throw new Error(`Cannot get current git hash: ${e.message}`);
237
237
  }
238
238
  return null;
239
239
  }
@@ -273,7 +273,7 @@ function stage(patterns, cwd) {
273
273
  });
274
274
  }
275
275
  catch (e) {
276
- console.error("Cannot stage changes", e.message);
276
+ throw new Error(`Cannot stage changes: ${e.message}`);
277
277
  }
278
278
  }
279
279
  exports.stage = stage;
@@ -281,13 +281,11 @@ function commit(message, cwd, options = []) {
281
281
  try {
282
282
  const commitResults = git(["commit", "-m", message, ...options], { cwd });
283
283
  if (!commitResults.success) {
284
- console.error("Cannot commit changes");
285
- console.log(commitResults.stdout);
286
- console.error(commitResults.stderr);
284
+ throw new Error(`Cannot commit changes: ${commitResults.stdout} ${commitResults.stderr}`);
287
285
  }
288
286
  }
289
287
  catch (e) {
290
- console.error("Cannot commit changes", e.message);
288
+ throw new Error(`Cannot commit changes: ${e.message}`);
291
289
  }
292
290
  }
293
291
  exports.commit = commit;
@@ -365,18 +363,42 @@ function normalizeRepoUrl(repositoryUrl) {
365
363
  return "";
366
364
  }
367
365
  }
368
- function getDefaultRemoteBranch(branch = "master", cwd) {
366
+ function getDefaultRemoteBranch(branch, cwd) {
369
367
  const defaultRemote = getDefaultRemote(cwd);
368
+ const showRemote = git(["remote", "show", defaultRemote], { cwd });
369
+ /**
370
+ * The `showRemote` returns something like this in stdout:
371
+ *
372
+ * * remote origin
373
+ * Fetch URL: ../monorepo-upstream/
374
+ * Push URL: ../monorepo-upstream/
375
+ * HEAD branch: main
376
+ *
377
+ */
378
+ const headBranchLine = showRemote.stdout.split(/\n/).find(line => line.includes('HEAD branch'));
379
+ let remoteDefaultBranch;
380
+ if (headBranchLine) {
381
+ remoteDefaultBranch = headBranchLine.replace(/^\s*HEAD branch:\s+/, '');
382
+ }
383
+ branch = branch || remoteDefaultBranch || getDefaultBranch(cwd);
370
384
  return `${defaultRemote}/${branch}`;
371
385
  }
372
386
  exports.getDefaultRemoteBranch = getDefaultRemoteBranch;
387
+ function getDefaultBranch(cwd) {
388
+ const result = git(["config", "init.defaultBranch"], { cwd });
389
+ if (!result.success) {
390
+ // Default to the legacy 'master' for backwards compat and old git clients
391
+ return "master";
392
+ }
393
+ return result.stdout.trim();
394
+ }
395
+ exports.getDefaultBranch = getDefaultBranch;
373
396
  function getDefaultRemote(cwd) {
374
397
  let packageJson;
375
398
  try {
376
399
  packageJson = JSON.parse(fs_1.default.readFileSync(path_1.default.join(paths_1.findGitRoot(cwd), "package.json")).toString());
377
400
  }
378
401
  catch (e) {
379
- console.log("failed to read package.json");
380
402
  throw new Error("invalid package.json detected");
381
403
  }
382
404
  const { repository } = packageJson;
@@ -402,7 +424,6 @@ function getDefaultRemote(cwd) {
402
424
  }
403
425
  }
404
426
  }
405
- console.log(`Defaults to "origin"`);
406
427
  return "origin";
407
428
  }
408
429
  exports.getDefaultRemote = getDefaultRemote;
@@ -4,3 +4,4 @@
4
4
  */
5
5
  export declare function setupFixture(fixtureName: string): string;
6
6
  export declare function cleanupFixtures(): void;
7
+ export declare function setupLocalRemote(cwd: string, remoteName: string, fixtureName: string): void;
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const path_1 = __importDefault(require("path"));
7
7
  const find_up_1 = __importDefault(require("find-up"));
8
8
  const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const fs_extra_2 = __importDefault(require("fs-extra"));
9
10
  const tmp_1 = __importDefault(require("tmp"));
10
11
  const git_1 = require("../git");
11
12
  // tmp is supposed to be able to clean up automatically, but this doesn't always work within jest.
@@ -34,6 +35,12 @@ function setupFixture(fixtureName) {
34
35
  fs_extra_1.default.mkdirpSync(cwd);
35
36
  fs_extra_1.default.copySync(fixturePath, cwd);
36
37
  git_1.init(cwd, "test@test.email", "test user");
38
+ // Make the 'main' branch the default in the test repo
39
+ // ensure that the configuration for this repo does not collide
40
+ // with any global configuration the user had made, so we have
41
+ // a 'fixed' value for our tests, regardless of user configuration
42
+ git_1.gitFailFast(['symbolic-ref', 'HEAD', 'refs/heads/main'], { cwd });
43
+ git_1.gitFailFast(['config', 'init.defaultBranch', 'main'], { cwd });
37
44
  git_1.stageAndCommit(["."], "test", cwd);
38
45
  return cwd;
39
46
  }
@@ -45,3 +52,16 @@ function cleanupFixtures() {
45
52
  }
46
53
  }
47
54
  exports.cleanupFixtures = cleanupFixtures;
55
+ function setupLocalRemote(cwd, remoteName, fixtureName) {
56
+ // Create a seperate repo and configure it as a remote
57
+ const remoteCwd = setupFixture(fixtureName);
58
+ const remoteUrl = remoteCwd.replace(/\\/g, "/");
59
+ git_1.gitFailFast(["remote", "add", remoteName, remoteUrl], { cwd });
60
+ // Configure url in package.json
61
+ const pkgJsonPath = path_1.default.join(cwd, "package.json");
62
+ const pkgJson = fs_extra_2.default.readJSONSync(pkgJsonPath);
63
+ fs_extra_2.default.writeJSONSync(pkgJsonPath, Object.assign(Object.assign({}, pkgJson), { repository: {
64
+ url: remoteUrl
65
+ } }));
66
+ }
67
+ exports.setupLocalRemote = setupLocalRemote;
@@ -3,4 +3,4 @@ import { nameAtVersion } from "./nameAtVersion";
3
3
  export declare function parseLockFile(packageRoot: string): Promise<ParsedLock>;
4
4
  export { nameAtVersion };
5
5
  export { queryLockFile } from "./queryLockFile";
6
- export * from './types';
6
+ export * from "./types";
@@ -10,12 +10,14 @@ var __importStar = (this && this.__importStar) || function (mod) {
10
10
  return result;
11
11
  };
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
+ // NOTE: never place the import of lockfile implementation here, as it slows down the library as a whole
13
14
  const find_up_1 = __importDefault(require("find-up"));
14
15
  const fs_extra_1 = __importDefault(require("fs-extra"));
15
16
  const read_yaml_file_1 = __importDefault(require("read-yaml-file"));
16
17
  const nameAtVersion_1 = require("./nameAtVersion");
17
18
  exports.nameAtVersion = nameAtVersion_1.nameAtVersion;
18
19
  const parsePnpmLock_1 = require("./parsePnpmLock");
20
+ const parseNpmLock_1 = require("./parseNpmLock");
19
21
  const memoization = {};
20
22
  async function parseLockFile(packageRoot) {
21
23
  const yarnLockPath = await find_up_1.default(["yarn.lock", "common/config/rush/yarn.lock"], { cwd: packageRoot });
@@ -41,7 +43,27 @@ async function parseLockFile(packageRoot) {
41
43
  memoization[pnpmLockPath] = parsed;
42
44
  return memoization[pnpmLockPath];
43
45
  }
44
- throw new Error("You do not have either yarn.lock nor pnpm-lock.yaml. Please use one of these package managers");
46
+ // Third, try for npm workspaces
47
+ let npmLockPath = await find_up_1.default(["package-lock.json"], { cwd: packageRoot });
48
+ if (npmLockPath) {
49
+ if (memoization[npmLockPath]) {
50
+ return memoization[npmLockPath];
51
+ }
52
+ let npmLockJson;
53
+ try {
54
+ npmLockJson = fs_extra_1.default.readFileSync(npmLockPath);
55
+ }
56
+ catch (_a) {
57
+ throw new Error("Couldn’t parse package-lock.json.");
58
+ }
59
+ const npmLock = JSON.parse(npmLockJson.toString());
60
+ if (!(npmLock === null || npmLock === void 0 ? void 0 : npmLock.lockfileVersion) || npmLock.lockfileVersion < 2) {
61
+ throw new Error(`Your package-lock.json version is not supported: lockfileVersion is ${npmLock.lockfileVersion}. You need npm version 7 or above and package-lock version 2 or above. Please, upgrade npm or choose a different package manager.`);
62
+ }
63
+ memoization[npmLockPath] = parseNpmLock_1.parseNpmLock(npmLock);
64
+ return memoization[npmLockPath];
65
+ }
66
+ throw new Error("You do not have yarn.lock, pnpm-lock.yaml or package-lock.json. Please use one of these package managers.");
45
67
  }
46
68
  exports.parseLockFile = parseLockFile;
47
69
  var queryLockFile_1 = require("./queryLockFile");
@@ -0,0 +1,2 @@
1
+ import { ParsedLock, NpmLockFile } from "./types";
2
+ export declare const parseNpmLock: (lock: NpmLockFile) => ParsedLock;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseNpmLock = (lock) => {
4
+ var _a;
5
+ return ({
6
+ object: (_a = lock.dependencies) !== null && _a !== void 0 ? _a : {},
7
+ type: "success",
8
+ });
9
+ };
@@ -16,3 +16,34 @@ export interface PnpmLockFile {
16
16
  [name: string]: any;
17
17
  };
18
18
  }
19
+ export interface NpmWorkspacesInfo {
20
+ version: string;
21
+ workspaces: {
22
+ packages: string[];
23
+ };
24
+ }
25
+ export interface NpmSymlinkInfo {
26
+ resolved: string;
27
+ link: boolean;
28
+ integrity?: "sha512" | "sha1";
29
+ dev?: boolean;
30
+ optional?: boolean;
31
+ devOptional?: boolean;
32
+ dependencies?: {
33
+ [key: string]: LockDependency;
34
+ };
35
+ }
36
+ export interface NpmLockFile {
37
+ name: string;
38
+ version: string;
39
+ lockfileVersion?: 1 | 2 | 3;
40
+ requires?: boolean;
41
+ packages?: {
42
+ ""?: NpmWorkspacesInfo;
43
+ } & {
44
+ [key: string]: NpmSymlinkInfo | LockDependency;
45
+ };
46
+ dependencies?: {
47
+ [key: string]: LockDependency;
48
+ };
49
+ }
@@ -15,4 +15,4 @@
15
15
  *
16
16
  * @returns string[] of package names that have changed
17
17
  */
18
- export declare function getChangedPackages(cwd: string, target?: string, ignoreGlobs?: string[]): string[];
18
+ export declare function getChangedPackages(cwd: string, target: string | undefined, ignoreGlobs?: string[]): string[];
@@ -24,8 +24,9 @@ const path_1 = __importDefault(require("path"));
24
24
  *
25
25
  * @returns string[] of package names that have changed
26
26
  */
27
- function getChangedPackages(cwd, target = "origin/master", ignoreGlobs = []) {
27
+ function getChangedPackages(cwd, target, ignoreGlobs = []) {
28
28
  const workspaceInfo = getWorkspaces_1.getWorkspaces(cwd);
29
+ target = target || git_1.getDefaultRemoteBranch(undefined, cwd);
29
30
  let changes = [
30
31
  ...new Set([
31
32
  ...(git_1.getUntrackedChanges(cwd) || []),
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const implementations_1 = require("./implementations");
4
+ const lerna_1 = require("./implementations/lerna");
5
+ const npm_1 = require("./implementations/npm");
4
6
  const pnpm_1 = require("./implementations/pnpm");
5
- const yarn_1 = require("./implementations/yarn");
6
7
  const rush_1 = require("./implementations/rush");
7
- const npm_1 = require("./implementations/npm");
8
- const lerna_1 = require("./implementations/lerna");
8
+ const yarn_1 = require("./implementations/yarn");
9
9
  const workspaceGetter = {
10
10
  yarn: yarn_1.getYarnWorkspaces,
11
11
  pnpm: pnpm_1.getPnpmWorkspaces,
@@ -10,7 +10,7 @@ function getNpmWorkspaceRoot(cwd) {
10
10
  }
11
11
  exports.getNpmWorkspaceRoot = getNpmWorkspaceRoot;
12
12
  function getNpmWorkspaces(cwd) {
13
- const yarnWorkspacesRoot = getNpmWorkspaceRoot(cwd);
14
- return packageJsonWorkspaces_1.getWorkspaceInfoFromWorkspaceRoot(yarnWorkspacesRoot);
13
+ const npmWorkspacesRoot = getNpmWorkspaceRoot(cwd);
14
+ return packageJsonWorkspaces_1.getWorkspaceInfoFromWorkspaceRoot(npmWorkspacesRoot);
15
15
  }
16
16
  exports.getNpmWorkspaces = getNpmWorkspaces;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "workspace-tools",
3
- "version": "0.15.1",
3
+ "version": "0.17.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -37,7 +37,7 @@
37
37
  "@types/node": ">=12.0.0",
38
38
  "@types/tmp": "^0.2.0",
39
39
  "@types/yarnpkg__lockfile": "^1.1.3",
40
- "beachball": "^2.2.0",
40
+ "beachball": "^2.17.0",
41
41
  "jest": "^25.0.0",
42
42
  "tmp": "^0.2.1",
43
43
  "ts-jest": "^25.5.1",