@pi-stef/catalog 0.3.1 → 0.3.3
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/package.json +1 -1
- package/src/commands/sync.ts +56 -5
package/package.json
CHANGED
package/src/commands/sync.ts
CHANGED
|
@@ -111,7 +111,13 @@ export async function syncCommand(
|
|
|
111
111
|
errors: [],
|
|
112
112
|
};
|
|
113
113
|
|
|
114
|
-
// --- 1.
|
|
114
|
+
// --- 1. Read local state BEFORE pulling ---------------------------------
|
|
115
|
+
// We need this to detect local-only packages and version changes
|
|
116
|
+
// (e.g., from `pi update`) that haven't been pushed yet.
|
|
117
|
+
const localCatalogBeforePull = readCatalog(ctx.home);
|
|
118
|
+
const localLockBeforePull = readLock(ctx.home);
|
|
119
|
+
|
|
120
|
+
// --- 2. Pull remote catalog (into memory only) ---------------------------
|
|
115
121
|
let remoteCatalog = false;
|
|
116
122
|
let pulledData: { catalog: CatalogYaml; lock: LockFile } | undefined;
|
|
117
123
|
try {
|
|
@@ -124,9 +130,48 @@ export async function syncCommand(
|
|
|
124
130
|
summary.errors.push(message);
|
|
125
131
|
}
|
|
126
132
|
|
|
127
|
-
// ---
|
|
133
|
+
// --- 3. Reconcile --------------------------------------------------------
|
|
128
134
|
// Use pulled catalog if available, otherwise read from disk
|
|
129
|
-
|
|
135
|
+
let catalog = pulledData ? pulledData.catalog : readCatalog(ctx.home);
|
|
136
|
+
|
|
137
|
+
// Merge local-only packages into the catalog.
|
|
138
|
+
// When a user adds a package locally (ct add) and then syncs, the pull
|
|
139
|
+
// would overwrite their addition. Detect local packages not in the remote
|
|
140
|
+
// and merge them back so they get pushed.
|
|
141
|
+
let hasLocalOnlyPackages = false;
|
|
142
|
+
if (pulledData) {
|
|
143
|
+
for (const [key, pkg] of Object.entries(localCatalogBeforePull.packages)) {
|
|
144
|
+
if (!(key in catalog.packages)) {
|
|
145
|
+
catalog.packages[key] = pkg;
|
|
146
|
+
hasLocalOnlyPackages = true;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Detect local lock changes (e.g., from `pi update` bumping versions).
|
|
152
|
+
// If the local lock has different versions than the remote lock, we need
|
|
153
|
+
// to push so the remote gist reflects the actual installed state.
|
|
154
|
+
let hasLocalLockChanges = false;
|
|
155
|
+
if (pulledData) {
|
|
156
|
+
const remoteLock = pulledData.lock;
|
|
157
|
+
for (const [key, localEntry] of Object.entries(localLockBeforePull.packages)) {
|
|
158
|
+
const remoteEntry = remoteLock.packages[key];
|
|
159
|
+
if (!remoteEntry || remoteEntry.version !== localEntry.version) {
|
|
160
|
+
hasLocalLockChanges = true;
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Also check for packages in remote but removed locally
|
|
165
|
+
if (!hasLocalLockChanges) {
|
|
166
|
+
for (const key of Object.keys(remoteLock.packages)) {
|
|
167
|
+
if (!(key in localLockBeforePull.packages)) {
|
|
168
|
+
hasLocalLockChanges = true;
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
130
175
|
const installed = scanInstalled(ctx.home);
|
|
131
176
|
|
|
132
177
|
// Build catalog entries for reconcile
|
|
@@ -206,7 +251,7 @@ export async function syncCommand(
|
|
|
206
251
|
const hasGist = readCachedGistId(ctx.home) !== undefined;
|
|
207
252
|
const localHasPackages = Object.keys(catalog.packages).length > 0;
|
|
208
253
|
|
|
209
|
-
if (force || summary.actionCount > 0 || (!hasGist && localHasPackages)) {
|
|
254
|
+
if (force || summary.actionCount > 0 || hasLocalOnlyPackages || hasLocalLockChanges || (!hasGist && localHasPackages)) {
|
|
210
255
|
try {
|
|
211
256
|
const updatedCatalog = readCatalog(ctx.home);
|
|
212
257
|
const updatedLock = readLock(ctx.home);
|
|
@@ -237,7 +282,7 @@ export async function syncCommand(
|
|
|
237
282
|
}
|
|
238
283
|
}
|
|
239
284
|
|
|
240
|
-
if (summary.actionCount === 0 && summary.errors.length === 0 && !force) {
|
|
285
|
+
if (summary.actionCount === 0 && summary.errors.length === 0 && !force && !hasLocalOnlyPackages && !hasLocalLockChanges) {
|
|
241
286
|
ctx.ui.notify("Catalog already up to date.", "info");
|
|
242
287
|
return;
|
|
243
288
|
}
|
|
@@ -247,6 +292,12 @@ export async function syncCommand(
|
|
|
247
292
|
if (summary.pulled) {
|
|
248
293
|
parts.push("Pulled remote catalog.");
|
|
249
294
|
}
|
|
295
|
+
if (hasLocalOnlyPackages) {
|
|
296
|
+
parts.push("Merged local-only packages.");
|
|
297
|
+
}
|
|
298
|
+
if (hasLocalLockChanges) {
|
|
299
|
+
parts.push("Pushed local version updates.");
|
|
300
|
+
}
|
|
250
301
|
if (plan.installs.length > 0) {
|
|
251
302
|
parts.push(`${plan.installs.length} install(s): ${plan.installs.map((a) => a.key).join(", ")}`);
|
|
252
303
|
}
|