Skip to content

Commit d17f5b3

Browse files
authored
fix: trigger watch on symlink addition/removal in current/ folder (#111)
1 parent 2de1b50 commit d17f5b3

File tree

7 files changed

+102
-35
lines changed

7 files changed

+102
-35
lines changed

__tests__/commit.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ describe.each([[undefined], ["My Commit Message"]])(
117117
it("can commit multi-file migration", async () => {
118118
mockFs({
119119
[`migrations/committed/000001${commitMessageSlug}.sql`]: MIGRATION_1_COMMITTED,
120-
"migrations/current": MIGRATION_MULTIFILE_FILES,
120+
...MIGRATION_MULTIFILE_FILES,
121121
});
122122

123123
await commit(settings, commitMessage);
@@ -138,7 +138,7 @@ describe.each([[undefined], ["My Commit Message"]])(
138138
it("throws on invalid message", async () => {
139139
mockFs({
140140
[`migrations/committed/000001${commitMessageSlug}.sql`]: MIGRATION_1_COMMITTED,
141-
"migrations/current": MIGRATION_MULTIFILE_FILES,
141+
...MIGRATION_MULTIFILE_FILES,
142142
});
143143

144144
const promise = commit(

__tests__/helpers.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,14 @@ export const makeMigrations = (commitMessage?: string) => {
255255
}\n\n${MIGRATION_NOTRX_TEXT.trim()}\n`;
256256

257257
const MIGRATION_MULTIFILE_FILES = {
258-
"001.sql": "select 1;",
259-
"002-two.sql": "select 2;",
260-
"003.sql": "select 3;",
258+
"migrations/links/two.sql": "select 2;",
259+
"migrations/current": {
260+
"001.sql": "select 1;",
261+
"002-two.sql": mockFs.symlink({
262+
path: "../links/two.sql",
263+
}),
264+
"003.sql": "select 3;",
265+
},
261266
};
262267

263268
const MIGRATION_MULTIFILE_TEXT = `\

__tests__/uncommit.test.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,17 @@ describe.each([[undefined], ["My Commit Message"]])(
109109
});
110110
expect(await fsp.readFile("migrations/current/001.sql", "utf8")).toEqual(
111111
(commitMessage ? `--! Message: ${commitMessage}\n\n` : "") +
112-
MIGRATION_MULTIFILE_FILES["001.sql"].trim() +
112+
MIGRATION_MULTIFILE_FILES["migrations/current"]["001.sql"].trim() +
113113
"\n",
114114
);
115115
expect(
116116
await fsp.readFile("migrations/current/002-two.sql", "utf8"),
117-
).toEqual(MIGRATION_MULTIFILE_FILES["002-two.sql"].trim() + "\n");
117+
).toEqual(
118+
MIGRATION_MULTIFILE_FILES["migrations/links/two.sql"].trim() + "\n",
119+
);
118120
expect(await fsp.readFile("migrations/current/003.sql", "utf8")).toEqual(
119-
MIGRATION_MULTIFILE_FILES["003.sql"].trim() + "\n",
121+
MIGRATION_MULTIFILE_FILES["migrations/current"]["003.sql"].trim() +
122+
"\n",
120123
);
121124

122125
await commit(settings);

__tests__/watch.test.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ jest.mock("child_process");
22

33
import "./helpers"; // Has side-effects; must come first
44

5+
import * as mockFs from "mock-fs";
6+
57
import { _makeCurrentMigrationRunner, _watch } from "../src/commands/watch";
68
import { parseSettings } from "../src/settings";
9+
import { makeMigrations } from "./helpers";
710
import {
811
makeActionSpies,
912
mockCurrentSqlContentOnce,
@@ -14,6 +17,8 @@ import {
1417

1518
beforeEach(resetDb);
1619

20+
const { MIGRATION_MULTIFILE_FILES } = makeMigrations();
21+
1722
it("doesn't run current.sql if it's already up to date", async () => {
1823
const { settings, getActionCalls } = makeActionSpies();
1924
const parsedSettings = await parseSettings({
@@ -64,3 +69,54 @@ SELECT ':DATABASE_NAME', 2 * 2;
6469
"afterCurrent",
6570
]);
6671
});
72+
73+
it("watches symlinked files", async () => {
74+
const { settings, getActionCalls } = makeActionSpies();
75+
const parsedSettings = await parseSettings({
76+
connectionString: TEST_DATABASE_URL,
77+
...settings,
78+
});
79+
await setup(parsedSettings);
80+
const migrationRunner = _makeCurrentMigrationRunner(
81+
parsedSettings,
82+
false,
83+
false,
84+
);
85+
86+
expect(getActionCalls()).toEqual([]);
87+
mockFs({
88+
...MIGRATION_MULTIFILE_FILES,
89+
"migrations/links/two.sql": `\
90+
-- First migration
91+
SELECT ':DATABASE_NAME';
92+
`,
93+
});
94+
await migrationRunner();
95+
expect(getActionCalls()).toEqual(["beforeCurrent", "afterCurrent"]);
96+
97+
// This one is identical
98+
mockFs({
99+
...MIGRATION_MULTIFILE_FILES,
100+
"migrations/links/two.sql": `\
101+
-- Second migration; identical except for this comment
102+
SELECT ':DATABASE_NAME';
103+
`,
104+
});
105+
await migrationRunner();
106+
expect(getActionCalls()).toEqual(["beforeCurrent", "afterCurrent"]);
107+
108+
mockFs({
109+
...MIGRATION_MULTIFILE_FILES,
110+
"migrations/links/two.sql": `\
111+
-- Third migration; DIFFERENT!
112+
SELECT ':DATABASE_NAME', 2 * 2;
113+
`,
114+
});
115+
await migrationRunner();
116+
expect(getActionCalls()).toEqual([
117+
"beforeCurrent",
118+
"afterCurrent",
119+
"beforeCurrent",
120+
"afterCurrent",
121+
]);
122+
});

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
"@types/node": "^14.6.0",
4444
"@types/pg": "^7.14.1",
4545
"chalk": "^3.0.0",
46-
"chokidar": "^3.3.1",
46+
"chokidar": "^3.5.1",
4747
"json5": "^2.1.2",
4848
"pg": ">=6.5 <9",
4949
"pg-connection-string": "^2.1.0",

src/commands/watch.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,17 @@ export async function _watch(
224224
stabilityThreshold: 200,
225225
pollInterval: 100,
226226
},
227+
228+
/*
229+
* We don't want to run the queue too many times during startup; so we
230+
* call it once on the 'ready' event.
231+
*/
232+
ignoreInitial: true,
227233
});
234+
watcher.on("add", queue);
228235
watcher.on("change", queue);
229-
queue();
236+
watcher.on("unlink", queue);
237+
watcher.once("ready", queue);
230238
return Promise.resolve();
231239
}
232240
}

yarn.lock

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -420,12 +420,7 @@
420420
dependencies:
421421
"@types/node" "*"
422422

423-
"@types/node@*":
424-
version "13.9.1"
425-
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.9.1.tgz#96f606f8cd67fb018847d9b61e93997dabdefc72"
426-
integrity sha512-E6M6N0blf/jiZx8Q3nb0vNaswQeEyn0XlupO+xN6DtJ6r6IT4nXrTry7zhIfYvFCl3/8Cu6WIysmUBKiqV0bqQ==
427-
428-
"@types/node@^14.6.0":
423+
"@types/node@*", "@types/node@^14.6.0":
429424
version "14.6.0"
430425
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.0.tgz#7d4411bf5157339337d7cff864d9ff45f177b499"
431426
integrity sha512-mikldZQitV94akrc4sCcSjtJfsTKt4p+e/s0AGscVA6XArQ9kFclP+ZiYUMnq987rc6QlYxXv/EivqlfSLxpKA==
@@ -905,20 +900,20 @@ chardet@^0.7.0:
905900
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
906901
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
907902

908-
chokidar@^3.3.1:
909-
version "3.3.1"
910-
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.1.tgz#c84e5b3d18d9a4d77558fef466b1bf16bbeb3450"
911-
integrity sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==
903+
chokidar@^3.5.1:
904+
version "3.5.1"
905+
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a"
906+
integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==
912907
dependencies:
913908
anymatch "~3.1.1"
914909
braces "~3.0.2"
915910
glob-parent "~5.1.0"
916911
is-binary-path "~2.1.0"
917912
is-glob "~4.0.1"
918913
normalize-path "~3.0.0"
919-
readdirp "~3.3.0"
914+
readdirp "~3.5.0"
920915
optionalDependencies:
921-
fsevents "~2.1.2"
916+
fsevents "~2.3.1"
922917

923918
ci-info@^2.0.0:
924919
version "2.0.0"
@@ -1710,10 +1705,10 @@ fs.realpath@^1.0.0:
17101705
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
17111706
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
17121707

1713-
fsevents@^2.1.2, fsevents@~2.1.2:
1714-
version "2.1.2"
1715-
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805"
1716-
integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==
1708+
fsevents@^2.1.2, fsevents@~2.3.1:
1709+
version "2.3.2"
1710+
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
1711+
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
17171712

17181713
function-bind@^1.1.1:
17191714
version "1.1.1"
@@ -3303,10 +3298,10 @@ [email protected]:
33033298
dependencies:
33043299
split "^1.0.0"
33053300

3306-
picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.0.7:
3307-
version "2.2.1"
3308-
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a"
3309-
integrity sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==
3301+
picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1:
3302+
version "2.2.3"
3303+
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.3.tgz#465547f359ccc206d3c48e46a1bcb89bf7ee619d"
3304+
integrity sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==
33103305

33113306
pify@^2.0.0:
33123307
version "2.3.0"
@@ -3451,12 +3446,12 @@ read-pkg@^2.0.0:
34513446
normalize-package-data "^2.3.2"
34523447
path-type "^2.0.0"
34533448

3454-
readdirp@~3.3.0:
3455-
version "3.3.0"
3456-
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.3.0.tgz#984458d13a1e42e2e9f5841b129e162f369aff17"
3457-
integrity sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==
3449+
readdirp@~3.5.0:
3450+
version "3.5.0"
3451+
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e"
3452+
integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==
34583453
dependencies:
3459-
picomatch "^2.0.7"
3454+
picomatch "^2.2.1"
34603455

34613456
realpath-native@^1.1.0:
34623457
version "1.1.0"

0 commit comments

Comments
 (0)