sidecarsync 1.1.0 → 1.3.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/README.md +1 -1
- package/dist/cli.js +31 -15
- package/package.json +1 -1
- package/scripts/postinstall.js +29 -10
package/README.md
CHANGED
|
@@ -86,7 +86,7 @@ Sidecar takes over branch management there —
|
|
|
86
86
|
- [Standalone repos](docs/standalone.md) — a repo that is its own sidecar
|
|
87
87
|
- [Redaction](docs/redaction.md) — what's stripped from pushes, reviewing it, opting out
|
|
88
88
|
- [Editor search visibility](docs/editors.md) — making gitignored files searchable
|
|
89
|
-
- [Global vs local installs](docs/install.md) —
|
|
89
|
+
- [Global vs local installs](docs/install.md) — the newest install wins
|
|
90
90
|
- [All commands](docs/commands.md)
|
|
91
91
|
- [Uninstall & troubleshooting](docs/uninstall.md) — removing the daemon, service, and state
|
|
92
92
|
|
package/dist/cli.js
CHANGED
|
@@ -238,6 +238,15 @@ function projectDependsOnSidecar(projectRoot) {
|
|
|
238
238
|
return false;
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
|
+
function installedPackageVersion(projectRoot) {
|
|
242
|
+
const manifestPath = path2.join(projectRoot, "node_modules", PACKAGE_NAME, "package.json");
|
|
243
|
+
try {
|
|
244
|
+
const manifest = JSON.parse(fs2.readFileSync(manifestPath, "utf8"));
|
|
245
|
+
return manifest.name === PACKAGE_NAME ? manifest.version : undefined;
|
|
246
|
+
} catch {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
241
250
|
function shouldUseGlobalRegistry() {
|
|
242
251
|
return process.env[GLOBAL_EXEC_ENV] === "1" || !findDependencyRoot(process.cwd());
|
|
243
252
|
}
|
|
@@ -3696,7 +3705,7 @@ function cmdStatus(args) {
|
|
|
3696
3705
|
statusLine("main branch", config.branch);
|
|
3697
3706
|
statusLine("inbox branch", inbox);
|
|
3698
3707
|
if (!checkoutPresent) {
|
|
3699
|
-
statusLine("checkout", "missing", "bad");
|
|
3708
|
+
statusLine("checkout", "missing — run `sidecar init`", "bad");
|
|
3700
3709
|
printDaemonLine();
|
|
3701
3710
|
printLastSyncLine(root);
|
|
3702
3711
|
return 0;
|
|
@@ -3737,6 +3746,7 @@ function cmdStatusJson() {
|
|
|
3737
3746
|
branch: config.branch,
|
|
3738
3747
|
inbox,
|
|
3739
3748
|
checkout: checkoutPresent ? "present" : "missing",
|
|
3749
|
+
globalInstall: shouldUseGlobalRegistry() || Boolean(findGlobalSidecarExecutable()),
|
|
3740
3750
|
currentBranch: branch || undefined,
|
|
3741
3751
|
dirty: checkoutPresent ? Boolean(git(sidecarPath, ["status", "--porcelain"]).stdout.trim()) : undefined,
|
|
3742
3752
|
daemon: daemonHealth().text,
|
|
@@ -3752,8 +3762,12 @@ function pendingStatusInboxBranches(sidecarPath, config) {
|
|
|
3752
3762
|
return pendingInboxBranches(sidecarPath, config).filter((remoteBranch) => !isAncestor(sidecarPath, remoteBranch, base));
|
|
3753
3763
|
}
|
|
3754
3764
|
function daemonHealth() {
|
|
3755
|
-
if (!shouldUseGlobalRegistry())
|
|
3756
|
-
|
|
3765
|
+
if (!shouldUseGlobalRegistry()) {
|
|
3766
|
+
if (!findGlobalSidecarExecutable()) {
|
|
3767
|
+
return { text: `no global install — nothing syncs; \`npm install -g ${PACKAGE_SPEC}\``, role: "bad" };
|
|
3768
|
+
}
|
|
3769
|
+
return { text: "owned by the global install", role: "quiet" };
|
|
3770
|
+
}
|
|
3757
3771
|
const service = daemonServiceStatus();
|
|
3758
3772
|
if (!service.available)
|
|
3759
3773
|
return { text: service.message ?? "unavailable", role: "quiet" };
|
|
@@ -4175,10 +4189,9 @@ function localSidecarCliPath(root) {
|
|
|
4175
4189
|
const candidate = path9.join(root, "node_modules", PACKAGE_NAME, "dist", "cli.js");
|
|
4176
4190
|
if (!isFile(candidate))
|
|
4177
4191
|
return;
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
} catch {}
|
|
4192
|
+
const localVersion = installedPackageVersion(root);
|
|
4193
|
+
if (localVersion === undefined || compareVersions(localVersion, packageVersion()) <= 0)
|
|
4194
|
+
return;
|
|
4182
4195
|
return candidate;
|
|
4183
4196
|
}
|
|
4184
4197
|
function currentCliPath() {
|
|
@@ -5098,12 +5111,11 @@ var GLOBAL_EXEC_ENV3 = "SIDECAR_GLOBAL_EXEC";
|
|
|
5098
5111
|
var PACKAGE_NAME2 = "sidecarsync";
|
|
5099
5112
|
var GLOBAL_ONLY_COMMANDS = new Set(["daemon", "deinit", "register-install", "set-install-source", "update"]);
|
|
5100
5113
|
if (!process.env[SKIP_LOCAL_EXEC_ENV3]) {
|
|
5101
|
-
const
|
|
5102
|
-
if (
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
const result = spawnSync5(process.execPath, [localExecutable, ...process.argv.slice(2)], {
|
|
5114
|
+
const local = findLocalInstall(process.cwd(), fileURLToPath4(import.meta.url));
|
|
5115
|
+
if (local) {
|
|
5116
|
+
process.env[GLOBAL_EXEC_ENV3] = "1";
|
|
5117
|
+
if (local.newer && !GLOBAL_ONLY_COMMANDS.has(process.argv[2])) {
|
|
5118
|
+
const result = spawnSync5(process.execPath, [local.executable, ...process.argv.slice(2)], {
|
|
5107
5119
|
stdio: "inherit",
|
|
5108
5120
|
env: {
|
|
5109
5121
|
...process.env,
|
|
@@ -5119,13 +5131,13 @@ if (!process.env[SKIP_LOCAL_EXEC_ENV3]) {
|
|
|
5119
5131
|
}
|
|
5120
5132
|
}
|
|
5121
5133
|
process.exit(await main());
|
|
5122
|
-
function
|
|
5134
|
+
function findLocalInstall(start, self) {
|
|
5123
5135
|
let current = path11.resolve(start);
|
|
5124
5136
|
while (true) {
|
|
5125
5137
|
if (projectDependsOnSidecar2(current)) {
|
|
5126
5138
|
const candidate = path11.join(current, "node_modules", PACKAGE_NAME2, "dist", "cli.js");
|
|
5127
5139
|
if (isFile2(candidate) && !sameFile(candidate, self)) {
|
|
5128
|
-
return candidate;
|
|
5140
|
+
return { executable: candidate, newer: localIsNewer(current) };
|
|
5129
5141
|
}
|
|
5130
5142
|
}
|
|
5131
5143
|
const parent = path11.dirname(current);
|
|
@@ -5134,6 +5146,10 @@ function findLocalExecutable(start, self) {
|
|
|
5134
5146
|
current = parent;
|
|
5135
5147
|
}
|
|
5136
5148
|
}
|
|
5149
|
+
function localIsNewer(projectRoot) {
|
|
5150
|
+
const localVersion = installedPackageVersion(projectRoot);
|
|
5151
|
+
return localVersion !== undefined && compareVersions(localVersion, packageVersion()) > 0;
|
|
5152
|
+
}
|
|
5137
5153
|
function projectDependsOnSidecar2(projectRoot) {
|
|
5138
5154
|
const manifestPath = path11.join(projectRoot, "package.json");
|
|
5139
5155
|
if (!isFile2(manifestPath))
|
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -14,8 +14,7 @@ try {
|
|
|
14
14
|
enableDaemon(packageRoot);
|
|
15
15
|
recordInstallSource(packageRoot);
|
|
16
16
|
} else {
|
|
17
|
-
|
|
18
|
-
registerWithGlobalSidecar(packageRoot);
|
|
17
|
+
setUpLocalInstall(packageRoot);
|
|
19
18
|
}
|
|
20
19
|
} catch (error) {
|
|
21
20
|
console.warn(`sidecar: postinstall failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -61,10 +60,36 @@ function recordInstallSource(packageRoot) {
|
|
|
61
60
|
});
|
|
62
61
|
}
|
|
63
62
|
|
|
64
|
-
|
|
63
|
+
// The global install owns the daemon, so it is what makes a cloned checkout
|
|
64
|
+
// actually sync. Without it a clone here would leave the user with a sidecar
|
|
65
|
+
// directory that silently never updates — worse than no checkout at all.
|
|
66
|
+
function setUpLocalInstall(packageRoot) {
|
|
65
67
|
const projectRoot = findInstallProjectRoot();
|
|
66
68
|
if (!projectRoot || !fs.existsSync(path.join(projectRoot, ".sidecar"))) return;
|
|
67
69
|
|
|
70
|
+
const globalSidecar = findGlobalSidecar(packageRoot);
|
|
71
|
+
if (!globalSidecar) {
|
|
72
|
+
warnMissingGlobalSidecar();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
cloneIfMissing(packageRoot, projectRoot);
|
|
77
|
+
registerWithGlobalSidecar(globalSidecar, projectRoot);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function warnMissingGlobalSidecar() {
|
|
81
|
+
console.warn(
|
|
82
|
+
[
|
|
83
|
+
"sidecar: no global install found, so this repo's sidecar checkout was not cloned.",
|
|
84
|
+
"sidecar: without the global install there is no daemon, and nothing would sync.",
|
|
85
|
+
"sidecar: install it, then set this repo up:",
|
|
86
|
+
"sidecar: npm install -g sidecarsync",
|
|
87
|
+
"sidecar: sidecar init",
|
|
88
|
+
].join("\n"),
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function cloneIfMissing(packageRoot, projectRoot) {
|
|
68
93
|
const cliPath = path.join(packageRoot, "dist", "cli.js");
|
|
69
94
|
if (!fs.existsSync(cliPath)) return;
|
|
70
95
|
|
|
@@ -80,13 +105,7 @@ function cloneIfMissing(packageRoot) {
|
|
|
80
105
|
if (output) console.warn(output);
|
|
81
106
|
}
|
|
82
107
|
|
|
83
|
-
function registerWithGlobalSidecar(
|
|
84
|
-
const projectRoot = findInstallProjectRoot();
|
|
85
|
-
if (!projectRoot || !fs.existsSync(path.join(projectRoot, ".sidecar"))) return;
|
|
86
|
-
|
|
87
|
-
const globalSidecar = findGlobalSidecar(packageRoot);
|
|
88
|
-
if (!globalSidecar) return;
|
|
89
|
-
|
|
108
|
+
function registerWithGlobalSidecar(globalSidecar, projectRoot) {
|
|
90
109
|
const result = spawnSync(globalSidecar, ["register-install"], {
|
|
91
110
|
cwd: projectRoot,
|
|
92
111
|
encoding: "utf8",
|