@fairgarden/distribution 0.1.0-alpha.3 → 0.1.0-alpha.5
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/LICENSE +21 -0
- package/Readme.md +28 -20
- package/dist/cli.js +116 -26
- package/dist/cli.js.map +1 -1
- package/dist/extends.js +2 -2
- package/dist/extends.js.map +1 -1
- package/dist/forks.js +1 -1
- package/dist/forks.js.map +1 -1
- package/dist/inherit.d.ts +31 -0
- package/dist/inherit.d.ts.map +1 -1
- package/dist/inherit.js +43 -2
- package/dist/inherit.js.map +1 -1
- package/dist/overrides.d.ts.map +1 -1
- package/dist/overrides.js +42 -4
- package/dist/overrides.js.map +1 -1
- package/dist/readme.d.ts +32 -2
- package/dist/readme.d.ts.map +1 -1
- package/dist/readme.js +130 -24
- package/dist/readme.js.map +1 -1
- package/dist/release.d.ts.map +1 -1
- package/dist/release.js +8 -7
- package/dist/release.js.map +1 -1
- package/dist/scaffold.d.ts +14 -4
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +61 -20
- package/dist/scaffold.js.map +1 -1
- package/dist/verify.d.ts +26 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +87 -0
- package/dist/verify.js.map +1 -0
- package/dist/workflows.d.ts +44 -4
- package/dist/workflows.d.ts.map +1 -1
- package/dist/workflows.js +132 -38
- package/dist/workflows.js.map +1 -1
- package/package.json +4 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Connor Davis
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/Readme.md
CHANGED
|
@@ -2,29 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- fg:version -->
|
|
4
4
|
|
|
5
|
-
Version **0.1.0-alpha.
|
|
5
|
+
Version **0.1.0-alpha.5**
|
|
6
6
|
|
|
7
7
|
<!-- /fg:version -->
|
|
8
8
|
|
|
9
|
-
<!-- fg:releasing -->
|
|
10
|
-
|
|
11
|
-
## Releasing
|
|
12
|
-
|
|
13
|
-
This module releases on its own. `0.1.0-alpha.3` is what main is working towards,
|
|
14
|
-
not what is published — the version here is always the next one.
|
|
15
|
-
|
|
16
|
-
1. **Publish it.** Run the *Publish* workflow from the Actions tab, picking the
|
|
17
|
-
dist tag. It refuses if that version is already on npm.
|
|
18
|
-
2. **Move it on.** `pnpm release` — opens a pull request bumping this branch
|
|
19
|
-
to `0.1.0-alpha.4`, or `pnpm release --id rc` to change
|
|
20
|
-
identifier. A prerelease gets no maintenance branch; there is no released
|
|
21
|
-
line behind it yet.
|
|
22
|
-
|
|
23
|
-
Every push to main publishes `@fairgarden/distribution@canary`. A canary is not a release and
|
|
24
|
-
carries no promise; it is there so main can be tried without a checkout.
|
|
25
|
-
|
|
26
|
-
<!-- /fg:releasing -->
|
|
27
|
-
|
|
28
9
|
Ship a set of versioned modules together.
|
|
29
10
|
|
|
30
11
|
End users do not care about semver — they want to know how old their copy is,
|
|
@@ -95,3 +76,30 @@ fg-dist prerelease --major # start the next line on a branch, leaving main alo
|
|
|
95
76
|
|
|
96
77
|
Mounting a distribution's apps into one Next deployment is a separate concern,
|
|
97
78
|
handled by `@fairgarden/monolith`.
|
|
79
|
+
|
|
80
|
+
<!-- fg:releasing -->
|
|
81
|
+
|
|
82
|
+
## Releasing
|
|
83
|
+
|
|
84
|
+
This module releases on its own. `0.1.0-alpha.5` is what main is working towards,
|
|
85
|
+
not what is published — the version here is always the next one. Its release
|
|
86
|
+
notes are the top section of `CHANGELOG.md`, where every pull request adds a
|
|
87
|
+
line linking itself.
|
|
88
|
+
|
|
89
|
+
1. **Publish it.** Run the *Publish* workflow from the Actions tab, picking the
|
|
90
|
+
dist tag. It refuses if that version is already on npm. Once it is out, open
|
|
91
|
+
pull requests are held — their changelog check fails — so nothing is noted
|
|
92
|
+
under a version that has already shipped.
|
|
93
|
+
2. **Move it on.** `pnpm release` opens a pull request moving main to
|
|
94
|
+
`0.1.0-alpha.6` and starting its section of the changelog, or
|
|
95
|
+
`pnpm release --id rc` to change identifier. Merging it lifts the hold. A
|
|
96
|
+
prerelease gets no maintenance branch; there is no released line behind it
|
|
97
|
+
yet.
|
|
98
|
+
|
|
99
|
+
A held pull request goes on once it is brought up to date with main and its
|
|
100
|
+
line is moved into the new version's section.
|
|
101
|
+
|
|
102
|
+
Every push to main publishes `@fairgarden/distribution@canary`. A canary is not a release and
|
|
103
|
+
carries no promise; it is there so main can be tried without a checkout.
|
|
104
|
+
|
|
105
|
+
<!-- /fg:releasing -->
|
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,8 @@ import { mkdir, readFile } from 'node:fs/promises';
|
|
|
5
5
|
import { addModule } from "./add-module.js";
|
|
6
6
|
import { extractModule } from "./extract.js";
|
|
7
7
|
import { writeReadmes } from "./readme.js";
|
|
8
|
-
import {
|
|
8
|
+
import { verify } from "./verify.js";
|
|
9
|
+
import { toolRelease, writeDistributionChecks, writeDistributionWorkflow, writeWorkflows } from "./workflows.js";
|
|
9
10
|
import { writeOverrides } from "./overrides.js";
|
|
10
11
|
import { checkReleasable, planRelease, readRelease, release, releaseDistribution, reportToActions as reportRelease, startPrerelease, } from "./release.js";
|
|
11
12
|
import { reportToActions as reportCanary, stampCanary } from "./canary.js";
|
|
@@ -27,6 +28,7 @@ for (const stream of [process.stdout, process.stderr]) {
|
|
|
27
28
|
});
|
|
28
29
|
}
|
|
29
30
|
const USAGE = `Usage: fg-dist <command> [options]
|
|
31
|
+
pnpm dist <command> [options], in a repository fg-dist set up
|
|
30
32
|
|
|
31
33
|
Commands:
|
|
32
34
|
init <kind> [dir] Scaffold a repository; kind is "distribution", "monolith" or "module"
|
|
@@ -41,6 +43,7 @@ Commands:
|
|
|
41
43
|
release Move a module on from the release it just published
|
|
42
44
|
prerelease Start the next line on a branch, leaving main where it is
|
|
43
45
|
check Fail when this ships anything older than what it extends
|
|
46
|
+
verify Fail when a file fg-dist writes no longer says what is true (CI)
|
|
44
47
|
inherit Add the modules the distribution this extends ships, and this does not
|
|
45
48
|
sync Report which modules have newer versions available
|
|
46
49
|
bump [name...] Move modules to their newest non-major version; a fork merges it
|
|
@@ -73,6 +76,7 @@ Options:
|
|
|
73
76
|
--no-git Skip "git init" when scaffolding
|
|
74
77
|
--url <git-url> Remote the scaffolded repository will live at (init)
|
|
75
78
|
--extends <name> Distribution the scaffolded one extends (init distribution)
|
|
79
|
+
--copyright <holder> Who holds the copyright on its MIT license (init; default: git user.name)
|
|
76
80
|
--separate Scaffold a distribution whose apps deploy separately
|
|
77
81
|
--ssh Record a submodule's URL as given, without rewriting it
|
|
78
82
|
--no-verify Skip checking whether the https urls can be cloned
|
|
@@ -116,6 +120,7 @@ const parseArgs = (argv) => {
|
|
|
116
120
|
pr: undefined,
|
|
117
121
|
repo: undefined,
|
|
118
122
|
direct: false,
|
|
123
|
+
copyright: undefined,
|
|
119
124
|
};
|
|
120
125
|
for (let index = 0; index < argv.length; index += 1) {
|
|
121
126
|
const arg = argv[index];
|
|
@@ -177,6 +182,9 @@ const parseArgs = (argv) => {
|
|
|
177
182
|
else if (arg === '--no-push') {
|
|
178
183
|
args.push = false;
|
|
179
184
|
}
|
|
185
|
+
else if (arg === '--copyright') {
|
|
186
|
+
args.copyright = argv[++index];
|
|
187
|
+
}
|
|
180
188
|
else if (arg === '--direct') {
|
|
181
189
|
args.direct = true;
|
|
182
190
|
}
|
|
@@ -305,6 +313,28 @@ const modulesFor = (cwd, names) => {
|
|
|
305
313
|
}
|
|
306
314
|
return { root, modules };
|
|
307
315
|
};
|
|
316
|
+
/**
|
|
317
|
+
* Bring a distribution's readme up to what a command just changed.
|
|
318
|
+
*
|
|
319
|
+
* Its table names every module's version and pin, so a command that moves one
|
|
320
|
+
* leaves it stale — and \`verify\` fails the pull request that forgot. Only the
|
|
321
|
+
* distribution's own: a module's readme is the module's, and writing into one
|
|
322
|
+
* would leave its submodule dirty.
|
|
323
|
+
*/
|
|
324
|
+
const refreshReadme = async (root) => {
|
|
325
|
+
if (!isDistribution(root))
|
|
326
|
+
return;
|
|
327
|
+
try {
|
|
328
|
+
const { updates } = await writeReadmes(root, { modules: false });
|
|
329
|
+
for (const update of updates.filter((each) => each.changed)) {
|
|
330
|
+
process.stdout.write(`${path.relative(root, update.file)} lists what it ships now.\n`);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
catch (error) {
|
|
334
|
+
process.stderr.write(`The readme was not updated: ${error instanceof Error ? error.message : String(error)}\n` +
|
|
335
|
+
'Run `pnpm dist readme` once that is sorted.\n');
|
|
336
|
+
}
|
|
337
|
+
};
|
|
308
338
|
const pad = (values) => values.reduce((widest, value) => Math.max(widest, value.length), 0);
|
|
309
339
|
const main = async () => {
|
|
310
340
|
const args = parseArgs(process.argv.slice(2));
|
|
@@ -328,11 +358,22 @@ const main = async () => {
|
|
|
328
358
|
// A module is consumed as a submodule, so record the URL it will be
|
|
329
359
|
// cloned from in the form a keyless clone can use.
|
|
330
360
|
const origin = args.url ? (args.ssh ? args.url : toHttps(args.url)) : undefined;
|
|
361
|
+
// Who holds the copyright on the MIT license it starts under: as given, or
|
|
362
|
+
// whoever git says is making it.
|
|
363
|
+
let copyright = args.copyright;
|
|
364
|
+
if (!copyright) {
|
|
365
|
+
try {
|
|
366
|
+
copyright = execFileSync('git', ['config', 'user.name'], { encoding: 'utf8' }).trim() || undefined;
|
|
367
|
+
}
|
|
368
|
+
catch {
|
|
369
|
+
copyright = undefined;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
331
372
|
const files = kind === 'distribution'
|
|
332
|
-
? distributionRepo(name, origin, args.extends, { monolith: !args.separate })
|
|
373
|
+
? distributionRepo(name, origin, args.extends, { monolith: !args.separate, copyright })
|
|
333
374
|
: kind === 'monolith'
|
|
334
|
-
? monolithRepo(name, origin)
|
|
335
|
-
: moduleRepo(name, origin);
|
|
375
|
+
? monolithRepo(name, origin, { copyright })
|
|
376
|
+
: moduleRepo(name, origin, { copyright });
|
|
336
377
|
const written = await write(target, files);
|
|
337
378
|
if (args.git) {
|
|
338
379
|
try {
|
|
@@ -363,8 +404,8 @@ const main = async () => {
|
|
|
363
404
|
process.stdout.write(kind === 'module'
|
|
364
405
|
? 'Next: pnpm install, then commit and push so a distribution can add it.\n'
|
|
365
406
|
: args.extends && kind === 'distribution'
|
|
366
|
-
? `Next: pnpm install, then \`
|
|
367
|
-
: 'Next: pnpm install, then `
|
|
407
|
+
? `Next: pnpm install, then \`pnpm dist inherit\` to ship what ${args.extends} ships.\n`
|
|
408
|
+
: 'Next: pnpm install, then `pnpm dist add-module <url>` to ship a module.\n');
|
|
368
409
|
return 0;
|
|
369
410
|
}
|
|
370
411
|
if (args.command === 'add-module') {
|
|
@@ -401,7 +442,7 @@ const main = async () => {
|
|
|
401
442
|
else if (result.overridesError) {
|
|
402
443
|
process.stderr.write(`\nThe module is added, but the workspace overrides were not updated:\n` +
|
|
403
444
|
` ${result.overridesError}\n` +
|
|
404
|
-
'Run `
|
|
445
|
+
'Run `pnpm dist overrides` once that is sorted.\n');
|
|
405
446
|
}
|
|
406
447
|
if (result.mounted && result.monolithConfig) {
|
|
407
448
|
process.stdout.write(`Mounted at /${result.mount} in ${path.relative(args.cwd, result.monolithConfig)}\n`);
|
|
@@ -426,6 +467,9 @@ const main = async () => {
|
|
|
426
467
|
if (result.turbo) {
|
|
427
468
|
process.stdout.write("turbo.json: the monolith's build waits for its libraries, not its own build\n");
|
|
428
469
|
}
|
|
470
|
+
const root = repositoryRoot(args.cwd);
|
|
471
|
+
if (root)
|
|
472
|
+
await refreshReadme(root);
|
|
429
473
|
process.stdout.write(result.monolithPackageJson
|
|
430
474
|
? '\nRun pnpm install and `fg-monolith merge-package-json`.\n'
|
|
431
475
|
: '\nRun pnpm install.\n');
|
|
@@ -451,7 +495,7 @@ const main = async () => {
|
|
|
451
495
|
if (args.check) {
|
|
452
496
|
process.stderr.write(`\n${changed.length} readme(s) are out of date:\n${changed
|
|
453
497
|
.map((update) => ` ${path.relative(root, update.file)}`)
|
|
454
|
-
.join('\n')}\nRun \`
|
|
498
|
+
.join('\n')}\nRun \`pnpm dist readme\` to update them.\n`);
|
|
455
499
|
return 1;
|
|
456
500
|
}
|
|
457
501
|
process.stdout.write(`\nUpdated:\n${changed
|
|
@@ -478,7 +522,7 @@ const main = async () => {
|
|
|
478
522
|
' "publishConfig": { "access": "public" }\n');
|
|
479
523
|
}
|
|
480
524
|
process.stdout.write('\nIt publishes the manifest, recording every module it ships, and its policy. ' +
|
|
481
|
-
'Version it with `
|
|
525
|
+
'Version it with `pnpm release`, then run the workflow.\n');
|
|
482
526
|
return 0;
|
|
483
527
|
}
|
|
484
528
|
const updates = await writeWorkflows(root, {
|
|
@@ -486,10 +530,10 @@ const main = async () => {
|
|
|
486
530
|
dryRun: args.dryRun,
|
|
487
531
|
names: args.names,
|
|
488
532
|
});
|
|
489
|
-
// The distribution
|
|
490
|
-
// unless only some modules were named.
|
|
533
|
+
// The distribution has its own checks too — the changelog for policy
|
|
534
|
+
// changes, and what fg-dist writes — unless only some modules were named.
|
|
491
535
|
if (isDistribution(root) && args.names.length === 0) {
|
|
492
|
-
updates.push(await
|
|
536
|
+
updates.push(await writeDistributionChecks(root, { force: args.force, dryRun: args.dryRun }));
|
|
493
537
|
}
|
|
494
538
|
if (updates.length === 0) {
|
|
495
539
|
process.stdout.write('No modules here. Run this in a distribution, which is where the modules are.\n');
|
|
@@ -501,6 +545,14 @@ const main = async () => {
|
|
|
501
545
|
? `${update.relativePath} has one already\n`
|
|
502
546
|
: `${update.relativePath} ${update.files.join(', ')}\n`);
|
|
503
547
|
}
|
|
548
|
+
// A module's CI installs fg-dist from npm, so what these workflows run has
|
|
549
|
+
// to be in a release it can install.
|
|
550
|
+
const tool = await toolRelease();
|
|
551
|
+
if (tool && tool.floor !== tool.own) {
|
|
552
|
+
process.stderr.write(`\nfg-dist ${tool.own} is not released, so modules are given ^${tool.floor}, the newest that is.\n` +
|
|
553
|
+
`Whatever these workflows run that is new since then fails in the modules' CI until\n` +
|
|
554
|
+
`${tool.own} is published. Publish it, then run this again to move them up to it.\n`);
|
|
555
|
+
}
|
|
504
556
|
if (written.length === 0) {
|
|
505
557
|
process.stdout.write('\nEvery module already publishes. Pass --force to overwrite the workflows.\n');
|
|
506
558
|
return 0;
|
|
@@ -564,7 +616,7 @@ const main = async () => {
|
|
|
564
616
|
}
|
|
565
617
|
if (args.check) {
|
|
566
618
|
process.stderr.write(`\n${path.relative(root, file)} does not match the modules here.\n` +
|
|
567
|
-
'Run `
|
|
619
|
+
'Run `pnpm dist overrides` to update it.\n');
|
|
568
620
|
return 1;
|
|
569
621
|
}
|
|
570
622
|
process.stdout.write(`\nUpdated ${path.relative(root, file)}. Run \`pnpm install\` to take it up.\n`);
|
|
@@ -633,7 +685,7 @@ const main = async () => {
|
|
|
633
685
|
? `${plan.maintenance.branch} keeps ${released.split('.').slice(0, 2).join('.')}.x\n`
|
|
634
686
|
: 'stays on this line; nothing branches off\n'));
|
|
635
687
|
}
|
|
636
|
-
process.stdout.write(`\nOr \`
|
|
688
|
+
process.stdout.write(`\nOr \`pnpm dist prerelease --major\` to start the next line beside main, ` +
|
|
637
689
|
'without\nmoving main off this one.\n');
|
|
638
690
|
return 1;
|
|
639
691
|
}
|
|
@@ -735,7 +787,7 @@ const main = async () => {
|
|
|
735
787
|
process.stdout.write('turbo.json builds the policy once, before each service that uses it.\n');
|
|
736
788
|
return 0;
|
|
737
789
|
}
|
|
738
|
-
process.stdout.write(`${args.check ? 'turbo.json is missing' : 'Wrote'} ${differ.join(', ')}${args.check ? '; run
|
|
790
|
+
process.stdout.write(`${args.check ? 'turbo.json is missing' : 'Wrote'} ${differ.join(', ')}${args.check ? '; run pnpm dist policy setup.' : ' into turbo.json.'}\n`);
|
|
739
791
|
return args.check ? 1 : 0;
|
|
740
792
|
}
|
|
741
793
|
process.stderr.write('Usage: fg-dist policy <build|test|use|setup>\n');
|
|
@@ -763,6 +815,23 @@ const main = async () => {
|
|
|
763
815
|
`than ${report.parent?.name}@${report.parent?.version}.\n`);
|
|
764
816
|
return 0;
|
|
765
817
|
}
|
|
818
|
+
if (args.command === 'verify') {
|
|
819
|
+
const root = repositoryRoot(args.cwd);
|
|
820
|
+
if (!root)
|
|
821
|
+
throw new Error(`${args.cwd} is not inside a git repository.`);
|
|
822
|
+
const checks = await verify(root);
|
|
823
|
+
const width = pad(checks.map((check) => check.what));
|
|
824
|
+
for (const check of checks) {
|
|
825
|
+
if (check.ok) {
|
|
826
|
+
process.stdout.write(`ok ${check.what}\n`);
|
|
827
|
+
continue;
|
|
828
|
+
}
|
|
829
|
+
const problem = (check.problem ?? '').split('\n').join(`\n ${' '.repeat(width)} `);
|
|
830
|
+
process.stderr.write(`stale ${check.what.padEnd(width)} ${problem}\n` +
|
|
831
|
+
(check.fix ? ` ${' '.repeat(width)} Run \`${check.fix}\`.\n` : ''));
|
|
832
|
+
}
|
|
833
|
+
return checks.every((check) => check.ok) ? 0 : 1;
|
|
834
|
+
}
|
|
766
835
|
if (args.command === 'extract') {
|
|
767
836
|
const [target] = args.names;
|
|
768
837
|
if (!target) {
|
|
@@ -791,8 +860,11 @@ const main = async () => {
|
|
|
791
860
|
if (result.overridesError) {
|
|
792
861
|
process.stderr.write(`\nThe module is extracted, but the workspace overrides were not updated:\n` +
|
|
793
862
|
` ${result.overridesError}\n` +
|
|
794
|
-
'Run `
|
|
863
|
+
'Run `pnpm dist overrides` once that is sorted.\n');
|
|
795
864
|
}
|
|
865
|
+
const root = repositoryRoot(args.cwd);
|
|
866
|
+
if (root)
|
|
867
|
+
await refreshReadme(root);
|
|
796
868
|
process.stdout.write(`origin is ${result.url}\n`);
|
|
797
869
|
if (result.rewritten) {
|
|
798
870
|
process.stdout.write(`(rewritten from ${args.url}; a submodule is cloned without an SSH key)\n`);
|
|
@@ -863,7 +935,7 @@ const main = async () => {
|
|
|
863
935
|
process.stdout.write(` ${state.submodule.relativePath} ${state.submodule.url}` +
|
|
864
936
|
` -> ${toHttps(state.submodule.url)}\n`);
|
|
865
937
|
}
|
|
866
|
-
process.stdout.write('Run `
|
|
938
|
+
process.stdout.write('Run `pnpm dist use-https` to rewrite them. They also have to be ' +
|
|
867
939
|
'readable without credentials, which means public.\n');
|
|
868
940
|
}
|
|
869
941
|
// A pin the remote does not have breaks every other clone, a build host's first.
|
|
@@ -874,7 +946,7 @@ const main = async () => {
|
|
|
874
946
|
for (const state of unpushed) {
|
|
875
947
|
process.stdout.write(` ${state.submodule.relativePath} ${state.head.slice(0, 7)}\n`);
|
|
876
948
|
}
|
|
877
|
-
process.stdout.write('Push them — `
|
|
949
|
+
process.stdout.write('Push them — `pnpm dist contribute <name>` does, for a change on its way upstream.\n');
|
|
878
950
|
}
|
|
879
951
|
// A fork whose work upstream has taken can go back to upstream.
|
|
880
952
|
const returnable = states.filter((state) => canReturn(state));
|
|
@@ -883,7 +955,7 @@ const main = async () => {
|
|
|
883
955
|
for (const state of returnable) {
|
|
884
956
|
process.stdout.write(` ${state.submodule.relativePath} in ${canReturn(state)}\n`);
|
|
885
957
|
}
|
|
886
|
-
process.stdout.write('Keep them, or `
|
|
958
|
+
process.stdout.write('Keep them, or `pnpm dist unfork <name>` to go back to upstream.\n');
|
|
887
959
|
}
|
|
888
960
|
// An extension may move ahead of what it extends, never behind it.
|
|
889
961
|
const extendsReport = inspectExtends(root);
|
|
@@ -913,9 +985,9 @@ const main = async () => {
|
|
|
913
985
|
// A major is only held back when it is newer than the non-major target.
|
|
914
986
|
const held = upgradable.filter((state) => state.upgrades.major !== undefined);
|
|
915
987
|
process.stdout.write(`\n${upgradable.length} module(s) have newer versions. `);
|
|
916
|
-
process.stdout.write('Run `
|
|
988
|
+
process.stdout.write('Run `pnpm dist bump` to take them');
|
|
917
989
|
process.stdout.write(held.length > 0
|
|
918
|
-
? `, or \`
|
|
990
|
+
? `, or \`pnpm dist bump --major\` to include the ${held.length} major upgrade(s).\n`
|
|
919
991
|
: '.\n');
|
|
920
992
|
return 0;
|
|
921
993
|
}
|
|
@@ -964,7 +1036,7 @@ const main = async () => {
|
|
|
964
1036
|
try {
|
|
965
1037
|
const done = integrate(root, state, to, { push: args.push });
|
|
966
1038
|
process.stdout.write(done.how === 'moved'
|
|
967
|
-
? `${line} (fork: upstream has all of it; \`
|
|
1039
|
+
? `${line} (fork: upstream has all of it; \`pnpm dist unfork ${state.submodule.name}\` goes back)\n`
|
|
968
1040
|
: `${line} (fork: merged${done.pushed ? `, pushed to ${done.pushed}` : ', not pushed'})\n`);
|
|
969
1041
|
}
|
|
970
1042
|
catch (error) {
|
|
@@ -972,6 +1044,8 @@ const main = async () => {
|
|
|
972
1044
|
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
973
1045
|
}
|
|
974
1046
|
}
|
|
1047
|
+
if (!args.dryRun)
|
|
1048
|
+
await refreshReadme(root);
|
|
975
1049
|
process.stdout.write(args.dryRun
|
|
976
1050
|
? '\nDry run; nothing moved.\n'
|
|
977
1051
|
: '\nSubmodule pointers moved. Commit them to record the new versions.\n');
|
|
@@ -991,10 +1065,23 @@ const main = async () => {
|
|
|
991
1065
|
for (const module of result.blocked) {
|
|
992
1066
|
process.stderr.write(`${module.path} has something in it already, so ${module.name} was not added there.\n`);
|
|
993
1067
|
}
|
|
1068
|
+
// The parent's notice goes with what is built on it.
|
|
1069
|
+
const license = result.license;
|
|
1070
|
+
if (license.how === 'merged') {
|
|
1071
|
+
process.stdout.write(`LICENSE carries ${result.parent}'s copyright too: ${license.lines.join('; ')}\n`);
|
|
1072
|
+
}
|
|
1073
|
+
else if (license.how === 'copied') {
|
|
1074
|
+
process.stdout.write(`${license.file} keeps ${result.parent}'s license, which is not this one's.\n`);
|
|
1075
|
+
}
|
|
1076
|
+
else if (license.how === 'none') {
|
|
1077
|
+
process.stdout.write(`${result.parent} publishes no license to carry.\n`);
|
|
1078
|
+
}
|
|
994
1079
|
if (result.added.length === 0 && result.blocked.length === 0) {
|
|
995
1080
|
process.stdout.write(`Ships everything ${result.parent}@${result.parentVersion} ships already.\n`);
|
|
996
1081
|
return 0;
|
|
997
1082
|
}
|
|
1083
|
+
if (!args.dryRun && result.added.length > 0)
|
|
1084
|
+
await refreshReadme(root);
|
|
998
1085
|
process.stdout.write(args.dryRun
|
|
999
1086
|
? '\nDry run; nothing added.\n'
|
|
1000
1087
|
: `\nShips what ${result.parent}@${result.parentVersion} ships. Run pnpm install, then commit.\n`);
|
|
@@ -1058,11 +1145,12 @@ const main = async () => {
|
|
|
1058
1145
|
if (args.command === 'fork') {
|
|
1059
1146
|
const [name, url] = args.names;
|
|
1060
1147
|
if (!name || !url) {
|
|
1061
|
-
process.stderr.write('fork needs a module and the url of your fork:
|
|
1148
|
+
process.stderr.write('fork needs a module and the url of your fork: pnpm dist fork <name> <url>\n');
|
|
1062
1149
|
return 1;
|
|
1063
1150
|
}
|
|
1064
1151
|
const { root, modules } = modulesFor(args.cwd, [name]);
|
|
1065
1152
|
const result = forkModule(root, modules[0], url, { ssh: args.ssh, push: args.push });
|
|
1153
|
+
await refreshReadme(root);
|
|
1066
1154
|
process.stdout.write(`${modules[0].relativePath} is checked out from ${result.url}\n` +
|
|
1067
1155
|
`forked from ${result.upstream}, which .gitmodules records as its upstream\n`);
|
|
1068
1156
|
if (result.rewritten) {
|
|
@@ -1072,13 +1160,13 @@ const main = async () => {
|
|
|
1072
1160
|
? `Pinned commit pushed to ${result.branch}, where everything this distribution pins in the fork lives.\n`
|
|
1073
1161
|
: 'Nothing pushed. The pinned commit has to be on the fork before anyone else can check it out.\n');
|
|
1074
1162
|
process.stdout.write(`\nNext: make the change on a branch in ${modules[0].relativePath}, then ` +
|
|
1075
|
-
`\`
|
|
1163
|
+
`\`pnpm dist contribute ${modules[0].name}\`.\nCommit .gitmodules and ${modules[0].relativePath} here.\n`);
|
|
1076
1164
|
return 0;
|
|
1077
1165
|
}
|
|
1078
1166
|
if (args.command === 'contribute') {
|
|
1079
1167
|
const [name] = args.names;
|
|
1080
1168
|
if (!name) {
|
|
1081
|
-
process.stderr.write('contribute needs a module:
|
|
1169
|
+
process.stderr.write('contribute needs a module: pnpm dist contribute <name>\n');
|
|
1082
1170
|
return 1;
|
|
1083
1171
|
}
|
|
1084
1172
|
const { root, modules } = modulesFor(args.cwd, [name]);
|
|
@@ -1087,6 +1175,7 @@ const main = async () => {
|
|
|
1087
1175
|
process.stdout.write(`Would push ${result.branch} and open a pull request into ${describeRemote(result.repository)} ${result.base}.\n`);
|
|
1088
1176
|
return 0;
|
|
1089
1177
|
}
|
|
1178
|
+
await refreshReadme(root);
|
|
1090
1179
|
process.stdout.write(`Pushed ${result.branch}.\n`);
|
|
1091
1180
|
if (result.pinnedOn)
|
|
1092
1181
|
process.stdout.write(`Pinned commit kept on ${result.pinnedOn}, which outlives the pull request's branch.\n`);
|
|
@@ -1111,12 +1200,13 @@ const main = async () => {
|
|
|
1111
1200
|
if (args.command === 'unfork') {
|
|
1112
1201
|
const [name] = args.names;
|
|
1113
1202
|
if (!name) {
|
|
1114
|
-
process.stderr.write('unfork needs a module:
|
|
1203
|
+
process.stderr.write('unfork needs a module: pnpm dist unfork <name>\n');
|
|
1115
1204
|
return 1;
|
|
1116
1205
|
}
|
|
1117
1206
|
const { root, modules } = modulesFor(args.cwd, [name]);
|
|
1118
1207
|
const state = inspect(modules[0], { fetch: args.fetch });
|
|
1119
1208
|
const result = unforkModule(root, state, { to: args.to, major: args.major, force: args.force });
|
|
1209
|
+
await refreshReadme(root);
|
|
1120
1210
|
process.stdout.write(`${modules[0].relativePath} is checked out from ${result.url} again, at ${result.to}.\n` +
|
|
1121
1211
|
`Commit .gitmodules and ${modules[0].relativePath} here. The fork itself is left as it is.\n`);
|
|
1122
1212
|
return 0;
|